home *** CD-ROM | disk | FTP | other *** search
/ QRZ! Ham Radio 8 / QRZ Ham Radio Callsign Database - Volume 8.iso / pc / files / t_unix / j109lxa4.tar / nntpserv.c < prev    next >
C/C++ Source or Header  |  1994-06-04  |  62KB  |  5,519 lines

  1. /*
  2.  
  3.  *
  4.  
  5.  * NNTP Server/Client - See RFC977
  6.  
  7.  * Jeffrey R. Comstock. - NR0D - Bloomington, Minnesota USA
  8.  
  9.  * Copyright 1990 Jeffrey R. Comstock, All Rights Reserved.
  10.  
  11.  * Permission granted for non-commercial copying and use, provided
  12.  
  13.  * this notice is retained.
  14.  
  15.  *
  16.  
  17.  * DB3FL 9107xx: heavily rewritten and bug fixing in file-handling
  18.  
  19.  * ported to NOS by PE1NMB - 920120
  20.  
  21.  *
  22.  
  23.  * DB3FL: ihave, read & lzw ported to NOS by YC1DAV 920804
  24.  
  25.  *
  26.  
  27.  * Mods by PA0GRI
  28.  
  29.  */
  30.  
  31.  
  32.  
  33. #include <stdio.h>
  34.  
  35. #include <time.h>
  36.  
  37. #include <stdarg.h>
  38.  
  39. #include <ctype.h>
  40.  
  41. #include <setjmp.h>
  42.  
  43. #ifdef MSDOS
  44.  
  45. #include <dos.h>
  46.  
  47. #include <dir.h>
  48.  
  49. #endif
  50.  
  51. #include <sys/types.h>
  52.  
  53. #include <sys/stat.h>
  54.  
  55. #ifdef UNIX
  56.  
  57. #include <fcntl.h>
  58.  
  59. #endif
  60.  
  61. #ifdef MSDOS
  62.  
  63. #include <io.h>
  64.  
  65. #endif
  66.  
  67. #include <string.h>
  68.  
  69. #include "global.h"
  70.  
  71. #include "config.h"
  72.  
  73. #ifdef NNTPS
  74.  
  75. #include "mbuf.h"
  76.  
  77. #include "cmdparse.h"
  78.  
  79. #include "socket.h"
  80.  
  81. #include "iface.h"
  82.  
  83. #include "proc.h"
  84.  
  85. #include "smtp.h"
  86.  
  87. #include "commands.h"
  88.  
  89. #include "dirutil.h"
  90.  
  91. #include "ftp.h"
  92.  
  93. #include "netuser.h"
  94.  
  95. #include "nntp.h"
  96.  
  97. #include "session.h"
  98.  
  99. #include "files.h"
  100.  
  101. #include "smtp.h"
  102.  
  103. #include "bm.h"
  104.  
  105. #ifdef LESS_WHINING
  106.  
  107. #include "pc.h"
  108.  
  109. #include "nr4.h"
  110.  
  111. #include "netrom.h"
  112.  
  113. #include "udp.h"
  114.  
  115. #include "tcp.h"
  116.  
  117. #include "ip.h"
  118.  
  119. #include "usock.h"
  120.  
  121. #endif
  122.  
  123. #ifdef LZW
  124.  
  125. #include "lzw.h"
  126.  
  127. #endif
  128.  
  129.  
  130.  
  131. FILE *open_file __ARGS((char *name,char *mode,int s,int t));
  132. FILE *temp_file __ARGS((int s,int t));          /* NMB */
  133.  
  134. static int near make_dir __ARGS((char *path,int s));
  135. static int check_file __ARGS((char *path));
  136. static int make_path __ARGS((char *group));
  137. static int check_blank __ARGS((char *bp));
  138. static int dup_f __ARGS((FILE *in,FILE *out,struct nntpsv *mp));
  139. static int update_list __ARGS((struct nntpsv *a));
  140. static int get_path2 __ARGS((struct article *art));
  141. static int dofwd __ARGS((struct nntpsv *mp,FILE *f,FILE *history));
  142. static int getreply __ARGS((struct nntpsv *cb));
  143. static int newnews __ARGS((char *string,struct nntpsv *mp,FILE *f));
  144. static int recv_file __ARGS((FILE *fp,int s));
  145. static int check_article __ARGS((char *id));
  146. static int xfer_article2 __ARGS((FILE *f,struct nntpsv *mp));
  147. static int doarticle __ARGS((char *buf,struct nntpsv *mp));
  148. static int restreql __ARGS((register char *w,register char *s));
  149. static int check_one __ARGS((register char *str));
  150. static int32 make_nntime __ARGS((struct date *d,struct time *t,char *str));
  151. static int ngmatcha __ARGS((int (*func)(char *,char *),int dflt,struct g_list *ngspec,struct g_list *matchlist));
  152. static int get_path __ARGS((char *group,struct nntpsv *mp));
  153. static int get_pointer __ARGS((char *group,struct nntpsv *mp));
  154. static FILE *open_message __ARGS((struct nntpsv *mp,FILE *f));
  155. static int get_id __ARGS((char *bp,struct nntpsv *mp));
  156. static int art_ret __ARGS((struct nntpsv *mp));
  157. static int garbled __ARGS((FILE *f));
  158. static int donewnews __ARGS((char *string,struct nntpsv *mp));
  159. static int dogroup __ARGS((struct nntpsv *mp,char *buf));
  160. static int check_grp __ARGS((struct nntpsv *mp));
  161. static int get_next __ARGS((struct nntpsv *mp));
  162. static int get_last __ARGS((struct nntpsv *mp));
  163. void poll __ARGS((void *p));
  164. static int get_article2 __ARGS((struct nntpsv *mp,char *id));
  165. static int donnprofile __ARGS((int argc,char *argv[],void *p));
  166.  
  167.  
  168. /***************************************************************************/
  169.  
  170.  
  171.  
  172.  
  173.  
  174. #undef CONTROL                  /* reverse NNTP function (not implemented yet) */
  175.  
  176. #define LINE    80
  177.  
  178.  
  179.  
  180. #ifdef LZW
  181.  
  182. int LzwActive = 1;
  183.  
  184. #endif
  185.  
  186. static int Snntp = -1;          /* prototype socket for service */
  187.  
  188. static int16 Nntpquiet = 0;
  189.  
  190. static int16 NnIhave = 0;
  191.  
  192. int Filecheck = 0;              /* flag if file system has been checked */
  193.  
  194.  
  195.  
  196. struct post *Post = NULLPOST;
  197.  
  198. struct Servers *Nntpserver = NULLSERVER;
  199.  
  200.  
  201.  
  202. static char *Host       = NULLCHAR;
  203.  
  204. static char NEol[]      = ".\n";
  205.  
  206. static char msgid[]     = "Message-ID: ";
  207.  
  208. static char subj[]      = "Subject: ";
  209.  
  210. static char ngrps[]     = "Newsgroups: ";
  211.  
  212. static char frm[]       = "From: ";
  213.  
  214. static char replyto[]   = "Reply-To: ";
  215.  
  216. static char pth[]       = "Path: ";
  217.  
  218.  
  219.  
  220. /*############################ NNTP COMMANDS #################################*/
  221.  
  222.  
  223.  
  224. /* Command table */
  225.  
  226. static char *commands[] = {
  227.  
  228.     "quit",
  229.  
  230. #define QUIT_CMD        0
  231.  
  232.     "help",
  233.  
  234. #define HELP_CMD        1
  235.  
  236.     "list",
  237.  
  238. #define LIST_CMD        2
  239.  
  240.     "group",
  241.  
  242. #define GROUP_CMD       3
  243.  
  244.     "debug",
  245.  
  246. #define DEBUG_CMD       4
  247.  
  248.     "article",
  249.  
  250. #define ARTICLE_CMD     5
  251.  
  252.     "next",
  253.  
  254. #define NEXT_CMD        6
  255.  
  256.     "xinfo",
  257.  
  258. #define XINFO_CMD       7
  259.  
  260.     "ihave",
  261.  
  262. #define IHAVE_CMD       8
  263.  
  264.     "newnews",
  265.  
  266. #define NEWNEWS_CMD     9
  267.  
  268.     "head",
  269.  
  270. #define HEAD_CMD        10
  271.  
  272.     "body",
  273.  
  274. #define BODY_CMD        11
  275.  
  276.     "stat",
  277.  
  278. #define STAT_CMD        12
  279.  
  280.     "last",
  281.  
  282. #define LAST_CMD        13
  283.  
  284.     "slave",
  285.  
  286. #define SLAVE_CMD       14
  287.  
  288.     "xlzw",
  289.  
  290. #define XLZW_CMD        15
  291.  
  292.     NULLCHAR
  293.  
  294. };
  295.  
  296.  
  297.  
  298. static char artmsg[]    = " Article retrieved - ";
  299.  
  300.  
  301.  
  302. /*static char info[]      = "100 %s Info:\n";*/
  303.  
  304. static char xinfo[]     = "100 No info available\n";
  305.  
  306. static char debug[]     = "100 DEBUG %s\n";
  307.  
  308.  
  309.  
  310. static char nnversion[] = "20%s %s NNTP version %s ready at %s\n";
  311.  
  312. static char slave[]     = "202 SLAVE %s\n";
  313.  
  314. static char closing[]   = "203 Closing\n";
  315.  
  316. static char listarticle[]= "211 %u %u %u%s\n";
  317.  
  318. static char retrieve[]  = "220 %u%s%shead and body follow\n";
  319.  
  320. static char head[]      = "221 %u%s%sHead\n";
  321.  
  322. static char body[]      = "222 %u%s%sBody\n";
  323.  
  324. static char statistics[]= "223 %u%s%sStatistics\n";
  325.  
  326. static char sepcmd[]    = "223 %u%s%srequest text separately\n";
  327.  
  328. static char newnews_t[] = "230 New news by message id follows\n";
  329.  
  330. static char transok[]   = "235 Thanks\n";
  331.  
  332.  
  333.  
  334. static char sendart[]   = "335 Send article, end with .\n";
  335.  
  336.  
  337.  
  338. static char nogroup[]   = "411 No such newsgroup\n";
  339.  
  340. static char noselect[]  = "412 No newsgroup selected\n";
  341.  
  342. static char nonext[]    = "421 No next article\n";
  343.  
  344. static char noprev[]    = "422 No previous article\n";
  345.  
  346. static char noart[]     = "430 No such article\n";
  347.  
  348. static char notwanted[] = "435 Article not wanted - do not send it\n";
  349.  
  350. static char transnotok[]= "437 Article rejected - header garbled - do not try again\n";
  351.  
  352.  
  353.  
  354. static char badsyntax[] = "501 Syntax error\n";
  355.  
  356. static char error[]     = "503 Command not performed\n";
  357.  
  358. /*static char nospace[]   = "503 Not enough disk space left\n";*/
  359.  
  360. static char lowmem[]    = "503 System overloaded\n";
  361.  
  362. static char fatal[]     = "503 Fatal error FILE %s\n";
  363.  
  364.  
  365.  
  366. static char quitcmd[]   = "QUIT\n";
  367.  
  368. static char help[]      = "NNTP Server 1992,\n\n"
  369.  
  370.             "100 ARTICLE  BODY  GROUP   HEAD  HELP IHAVE\n"
  371.  
  372.             "100 LAST     LIST  NEWNEWS NEXT  QUIT STAT\n";
  373.  
  374.  
  375.  
  376. static void near
  377.  
  378. rip2(register char *s)
  379.  
  380. {
  381.  
  382.     register char *cp;
  383.  
  384.  
  385.  
  386.     if((cp = strpbrk(s,"\r\n")) != NULLCHAR)
  387.  
  388.         *cp = '\0';
  389.  
  390. }
  391.  
  392.  
  393.  
  394. /* main directory-creating routine
  395.  
  396.  * handles special chars in pathname - especially for MSDOS
  397.  
  398.  * returncode: -1 error; 0 success
  399.  
  400.  */
  401.  
  402. static int near
  403.  
  404. make_dir(path,s)
  405.  
  406. char *path;
  407.  
  408. int s;
  409.  
  410. {
  411.  
  412. #ifdef MSDOS
  413.     register char *cp;
  414. #endif
  415.  
  416.  
  417.  
  418.     if(path == NULLCHAR)
  419.  
  420.         return -1;
  421.  
  422. #ifdef MSDOS
  423.  
  424.     while((cp = strchr(path,'\\')) != NULLCHAR)
  425.  
  426.         *cp = '/';
  427.  
  428. #endif
  429.  
  430.     if (access(path,0)) {
  431.  
  432. #ifdef UNIX
  433.         if (mkdir(path, 0666)) {
  434.  
  435. #else
  436.  
  437.         if (mkdir(path)) {
  438.  
  439. #endif
  440.  
  441.             tprintf("Can't create %s: %s\n",path,sys_errlist[errno]);
  442.  
  443.             if(s)
  444.  
  445.                 usprintf(s,fatal,path);
  446.  
  447.             return -1;
  448.  
  449.         }
  450.  
  451.     }
  452.  
  453.     return 0;
  454.  
  455. }
  456.  
  457.  
  458.  
  459. /* main message-opening routine
  460.  
  461.  * returncode: NULLFILE if error; filepointer success */
  462.  
  463. static FILE *
  464. open_message(mp,f)
  465. struct nntpsv *mp;
  466. FILE *f;
  467.  
  468. {
  469.  
  470.     char line[LineLen];
  471.  
  472.  
  473.  
  474.     /* mp already checked */
  475.  
  476.  
  477.  
  478.     if(f != NULLFILE)
  479.  
  480.         fclose(f);
  481.  
  482.  
  483.  
  484.     sprintf(line,"%s/%u",mp->path,mp->pointer);
  485.  
  486.  
  487.  
  488.     if ((f = open_file(line,READ_TEXT,0,0)) == NULLFILE)
  489.  
  490.         usputs(mp->s,noart);
  491.  
  492.     return f;
  493.  
  494. }
  495.  
  496.  
  497.  
  498. /* file-receiving routine
  499.  
  500.  * returncode: -1 if error or 'recvline' faults; 0 success; 1 if blank line */
  501.  
  502. static int
  503. recv_file(fp,s)
  504. FILE *fp;
  505. int s;
  506.  
  507. {
  508.  
  509.     char line[LineLen];
  510.  
  511.     int check = 0;
  512.  
  513.  
  514.  
  515.     for (;;) {
  516.  
  517.         if (recvline(s,line,LineLen) == -1)
  518.  
  519.             return -1;
  520.  
  521.         rip2(line);
  522.  
  523.         if (strcmp(line,".") == 0) {
  524.  
  525.             return 0;
  526.  
  527.         }
  528.  
  529.         if(!check) {                    /* only enabled on first line! */
  530.  
  531.             check = 1;
  532.  
  533.             if (*line == '\0')      /* check for blank line */
  534.  
  535.                 return 1;
  536.  
  537.         }
  538.  
  539.         fprintf(fp,"%s\n",line);
  540.  
  541.     }
  542.  
  543. }
  544.  
  545.  
  546.  
  547. /* checks incoming article-id against existing articles
  548.  
  549.  * returncode: -1 if error; 1 if article exists; 0 no article found */
  550.  
  551. static int
  552. check_article(id)
  553. char *id;
  554.  
  555. {
  556.  
  557.     char *p, line[LineLen];
  558.  
  559.     FILE *f;
  560.  
  561.  
  562.  
  563.     if(id == NULLCHAR || (p = strchr(id,'<')) == NULLCHAR
  564.  
  565.       || (f = open_file(History,READ_TEXT,0,1)) == NULLFILE)
  566.  
  567.         return -1;
  568.  
  569.  
  570.  
  571.     for(;;) {
  572.  
  573.         if (fgets(line,LineLen,f) == NULL) {
  574.  
  575.             fclose(f);
  576.  
  577.             return 0;
  578.  
  579.         }
  580.  
  581.         if (strstr(line,p) != NULL) {
  582.  
  583.             fclose(f);
  584.  
  585.             return 1;
  586.  
  587.         }
  588.  
  589.     }
  590.  
  591. }
  592.  
  593.  
  594.  
  595. /* checks for not valid chars in a line
  596.  
  597.  * returncode: 0 if valid; 1 if invalid */
  598.  
  599. static int
  600. check_blank(bp)
  601. char *bp;
  602.  
  603. {
  604.  
  605.     if (strpbrk(bp,"!@#$%^&*()_+=<>,./?~`[]{}\\|0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ") == NULL)
  606.  
  607.         return 1;
  608.  
  609.     return 0;
  610.  
  611. }
  612.  
  613.  
  614.  
  615. /* main file-checking routine
  616.  
  617.  * returncode: -1 if error; 0 success */
  618.  
  619. static int
  620. check_file(path)
  621. char *path;
  622.  
  623. {
  624.  
  625.     if(path == NULLCHAR)
  626.  
  627.         return -1;
  628.  
  629.     if(access(path,0))
  630.  
  631.         return close(creat(path,S_IWRITE));
  632.  
  633.     return 0;
  634.  
  635. }
  636.  
  637.  
  638.  
  639. /* checks if two spaces exists in given string
  640.  
  641.  * returncode: -1 if error; 1 success */
  642.  
  643. static int
  644. check_one(str)
  645. register char *str;
  646.  
  647. {
  648.  
  649.     register char *cp;
  650.  
  651.  
  652.  
  653.     if(str == NULLCHAR || (cp = strchr(str,' ')) == NULLCHAR)
  654.  
  655.         return -1;
  656.  
  657.     cp++;
  658.  
  659.  
  660.  
  661.     if (strchr(cp,' ') == NULLCHAR)
  662.  
  663.         return -1;
  664.  
  665.  
  666.  
  667.     return 1;
  668.  
  669. }
  670.  
  671.  
  672.  
  673. /* checks the file-system used for NNTP
  674.  
  675.  * returncode: -1 if error; 0 success - and "Filecheck" is set to 1 */
  676.  
  677. static int
  678.  
  679. check_system(void)
  680.  
  681. {
  682.  
  683.     FILE *f;
  684.  
  685.     char line[LineLen];
  686.  
  687.     int error = 0;
  688.  
  689.  
  690.  
  691.     if (Post == NULLPOST)
  692.  
  693.         donnprofile(10,NULL,NULL);
  694.  
  695.  
  696.  
  697.     if(Filecheck)
  698.  
  699.         return 0;
  700.  
  701.  
  702.  
  703.     error  = make_dir(Forward,0);
  704.  
  705.     error |= check_file(Pointer);
  706.  
  707.     error |= check_file(History);
  708.  
  709.     error |= check_file(Active);
  710.  
  711.     error |= check_file(Poll);
  712.  
  713.  
  714.  
  715.     if(error)
  716.  
  717.         goto quit;
  718.  
  719.  
  720.  
  721.     sprintf(line,"%s/fwd.seq",Newsdir);
  722.  
  723.     if (access(line,0)) {
  724.  
  725.         if((f = open_file(line,"w+",0,1)) == NULLFILE) {
  726.  
  727.             goto quit;
  728.  
  729.         }
  730.  
  731.         fputs("1\n",f);
  732.  
  733.         fclose(f);
  734.  
  735.     }
  736.  
  737.     sprintf(line,"%s/sequence.seq",Mailqdir);
  738.  
  739.     if (access(line,0)) {
  740.  
  741.         if((f = open_file(line,"w+",0,1)) == NULLFILE) {
  742.  
  743.             goto quit;
  744.  
  745.         }
  746.  
  747.         fputs("1\n",f);
  748.  
  749.         fclose(f);
  750.  
  751.     }
  752.  
  753.     Filecheck = 1;
  754.  
  755.     return 0;
  756.  
  757.  
  758.  
  759. quit:
  760.  
  761.     Filecheck = 0;
  762.  
  763.     tputs("Error in NNTP file system\n");
  764.  
  765.     return -1;
  766.  
  767. }
  768.  
  769.  
  770.  
  771. /* handles the response code of an incoming msg
  772.  
  773.  * returncode: -1 error; 0 no code; value of response code on success */
  774.  
  775. static int
  776. getreply(cb)
  777. struct nntpsv *cb;
  778.  
  779. {
  780.  
  781.     int response;
  782.  
  783.  
  784.  
  785.     while(recvline(cb->s,cb->buf,LineLen) != -1) {
  786.  
  787.         /* skip informative messages and blank lines */
  788.  
  789.         if(cb->buf[0] == '\0' || cb->buf[0] == '1')
  790.  
  791.             continue;
  792.  
  793.         sscanf(cb->buf,"%d",&response);
  794.  
  795.         return (response < 500) ? response : -1;
  796.  
  797.     }
  798.  
  799.     return -1;
  800.  
  801. }
  802.  
  803.  
  804.  
  805. /* returncode: -1 error; 1 success; 0 no entry */
  806.  
  807. static int
  808. get_path(group,mp)
  809. char *group;
  810. struct nntpsv *mp;
  811.  
  812. {
  813.  
  814.     FILE *f;
  815.  
  816.     char line[LineLen], *cp;
  817.  
  818.  
  819.  
  820.     if(group == NULLCHAR || mp == NULLNNTPSV
  821.  
  822.       || (f = open_file(Pointer,READ_TEXT,mp->s,0)) == NULLFILE)
  823.  
  824.         return -1;
  825.  
  826.  
  827.  
  828.     group++;
  829.  
  830.  
  831.  
  832.     for (;;) {
  833.  
  834.         if (fgets(line,LineLen,f) == NULL)
  835.  
  836.             break;
  837.  
  838.         if (strcspn(line," ") != strlen(group))
  839.  
  840.             continue;
  841.  
  842.         if (strnicmp(group,line,strlen(group)) == 0) {
  843.  
  844.             cp = (strchr(line,' ')) + 1;
  845.  
  846.             if (mp->path != NULLCHAR)
  847.  
  848.                 free(mp->path);
  849.  
  850.             mp->path = strdup(cp);
  851.  
  852.             rip2(mp->path);
  853.  
  854.             fclose(f);
  855.  
  856.             return 1;
  857.  
  858.         }
  859.  
  860.     }
  861.  
  862.     fclose(f);
  863.  
  864.     return 0;
  865.  
  866. }
  867.  
  868.  
  869.  
  870. /* checkes if path to given article exists
  871.  
  872.  * returncode: -1 error; 1 success; 0 no path */
  873.  
  874. static int
  875. get_path2(art)
  876. struct article *art;
  877.  
  878. {
  879.  
  880.     FILE *f;
  881.  
  882.     char line[LineLen], *p;
  883.  
  884.  
  885.  
  886.     if(art->group == NULLCHAR
  887.  
  888.       || (f = open_file(Pointer,READ_TEXT,0,1)) == NULLFILE)
  889.  
  890.         return -1;
  891.  
  892.  
  893.  
  894.     p = art->group;
  895.  
  896.     art->path = NULLCHAR;
  897.  
  898.  
  899.  
  900.     for (;;) {
  901.  
  902.         if (fgets(line,LineLen,f) == NULL)
  903.  
  904.             break;
  905.  
  906.         if (strcspn(line," ") != strlen(p))
  907.  
  908.             continue;
  909.  
  910.         if (strnicmp(p,line,strlen(p)) == 0) {
  911.  
  912.             p = (strchr(line,' ')) + 1;
  913.  
  914.             if(art->path != NULLCHAR)
  915.  
  916.                 free(art->path);
  917.  
  918.             art->path = strdup(p);
  919.  
  920.             rip2(art->path);
  921.  
  922.             fclose(f);
  923.  
  924.             return 1;
  925.  
  926.         }
  927.  
  928.     }
  929.  
  930.     fclose(f);
  931.  
  932.     return 0;
  933.  
  934. }
  935.  
  936.  
  937.  
  938. /* returncode: -1 if error; 1 success; 0 no pointer */
  939.  
  940. static int
  941. get_pointer(group,mp)
  942. char *group;
  943. struct nntpsv *mp;
  944.  
  945. {
  946.  
  947.     FILE *f;
  948.  
  949.     char line[LineLen], *p;
  950.  
  951.  
  952.  
  953.     if(group == NULLCHAR || mp == NULLNNTPSV
  954.  
  955.       || (f = open_file(Active,READ_TEXT,mp->s,0)) == NULLFILE)
  956.  
  957.         return -1;
  958.  
  959.  
  960.  
  961.     group++;
  962.  
  963.  
  964.  
  965.     for (;;) {
  966.  
  967.         if (fgets(line,LineLen,f) == NULL)
  968.  
  969.             break;
  970.  
  971.         if (strcspn(line," ") != strlen(group))
  972.  
  973.             continue;
  974.  
  975.         if (strnicmp(group,line,strlen(group))==0) {
  976.  
  977.             p = strchr(line,' ');
  978.  
  979.             mp->last = (unsigned)atoi(p);
  980.  
  981.             p++;
  982.  
  983.             mp->first = (unsigned)atoi(strchr(p,' '));
  984.  
  985.             mp->pointer = (mp->first > mp->last ) ? 0 : mp->first;
  986.  
  987.             fclose(f);
  988.  
  989.             return 1;
  990.  
  991.         }
  992.  
  993.     }
  994.  
  995.     fclose(f);
  996.  
  997.     return 0;
  998.  
  999. }
  1000.  
  1001.  
  1002.  
  1003. /* creating path to a new newsgroup
  1004.  
  1005.  * handling of "." and "\" in pathnames especially MSDOS */
  1006.  
  1007. /* returncode: -1 error; 0 success */
  1008.  
  1009. static int
  1010. make_path(group)
  1011. char *group;
  1012.  
  1013. {
  1014.  
  1015.     FILE *f;
  1016.  
  1017.     char cp[LineLen], cp1[LineLen], *cp2;
  1018.  
  1019.     int got_it;
  1020.  
  1021.  
  1022.  
  1023.     if (group == NULLCHAR
  1024.  
  1025.       || (f = open_file(Pointer,APPEND_TEXT,0,1)) == NULLFILE)
  1026.  
  1027.         return -1;
  1028.  
  1029.  
  1030.  
  1031.     got_it = 0;
  1032.  
  1033.     strcpy(cp1,group);
  1034.  
  1035.  
  1036.  
  1037.     for(;;) {
  1038.  
  1039.         if((cp2 = strchr(cp1,'.')) != NULLCHAR)
  1040.  
  1041.             *cp2 = '\0';
  1042.  
  1043.         else
  1044.  
  1045.             got_it = 1;
  1046.  
  1047.  
  1048.  
  1049.         sprintf(cp,"%s/%s",Newsdir,cp1);
  1050.  
  1051.  
  1052.  
  1053.         if(make_dir(cp,0)) {
  1054.  
  1055.             fclose(f);
  1056.  
  1057.             return -1;
  1058.  
  1059.         }
  1060.  
  1061.         if(got_it) {
  1062.  
  1063.             fprintf(f,"%s %s\n",group,cp);
  1064.  
  1065.             fclose(f);
  1066.  
  1067.             return 0;
  1068.  
  1069.         }
  1070.  
  1071.         *cp2 = '/';
  1072.  
  1073.     }
  1074.  
  1075. }
  1076.  
  1077.  
  1078.  
  1079. static int
  1080. update_list(a)
  1081. struct nntpsv *a;
  1082.  
  1083. {
  1084.  
  1085.     FILE *f, *t;
  1086.  
  1087.     char *p, *p1, l2[LineLen];
  1088.  
  1089.  
  1090.  
  1091.     if((f = open_file(Active,READ_TEXT,a->s,0)) == NULLFILE)
  1092.  
  1093.         return -1;
  1094.  
  1095.  
  1096.  
  1097.     if ((t = temp_file(0,1)) == NULLFILE) {
  1098.  
  1099.         fclose(f);
  1100.  
  1101.         return -1;
  1102.  
  1103.     }
  1104.  
  1105.     p1 = a->ap->group;
  1106.  
  1107.     a->ap->number = 0;
  1108.  
  1109.     for (;;) {
  1110.  
  1111.         if (fgets(a->buf,LineLen,f) == NULL)
  1112.  
  1113.             break;
  1114.  
  1115.         a->ap->tmpu = strcspn(a->buf," ");
  1116.  
  1117.         strncpy(l2,a->buf,a->ap->tmpu);
  1118.  
  1119.         l2[a->ap->tmpu] = '\0';
  1120.  
  1121.         if (strcmp(p1,l2) == 0) {
  1122.  
  1123.             p = strchr(a->buf,' ') + 1;
  1124.  
  1125.             a->ap->number = (unsigned)atoi(p);
  1126.  
  1127.             (a->ap->number)++;
  1128.  
  1129.             p = strchr(p,' ');
  1130.  
  1131.             fprintf(t,"%s %5.5u%s",p1,a->ap->number,p);
  1132.  
  1133.         } else
  1134.  
  1135.             fputs(a->buf,t);
  1136.  
  1137.     }
  1138.  
  1139.     fclose(f);
  1140.  
  1141.     rewind(t);
  1142.  
  1143.     if ((f = open_file(Active,WRITE_TEXT,a->s,0)) == NULLFILE) {
  1144.  
  1145.         fclose(t);
  1146.  
  1147.         return -1;
  1148.  
  1149.     }
  1150.  
  1151.     for(;;) {
  1152.  
  1153.         if (fgets(a->buf,LineLen,t) == NULL)
  1154.  
  1155.             break;
  1156.  
  1157.         fputs(a->buf,f);
  1158.  
  1159.     }
  1160.  
  1161.     fclose(t);
  1162.  
  1163.     if (a->ap->number == 0) {
  1164.  
  1165.         make_path(a->ap->group);
  1166.  
  1167.         a->ap->number = 1;
  1168.  
  1169.         fprintf(f,"%s 00001 00001 y\n",a->ap->group);
  1170.  
  1171.     }
  1172.  
  1173.     fclose(f);
  1174.  
  1175.     return (a->ap->number);
  1176.  
  1177. }
  1178.  
  1179.  
  1180.  
  1181. /* returncode: -1 error; 0 success */
  1182.  
  1183. static int
  1184. dup_f(in,out,mp)
  1185. FILE *in;
  1186. FILE *out;
  1187. struct nntpsv *mp;
  1188.  
  1189. /* Path: bug in col 1 of article body bug fixed by G4JEC 901019....*/
  1190.  
  1191. {
  1192.  
  1193.     char *p;
  1194.  
  1195.     int blank_line_flag = 1;
  1196.  
  1197.  
  1198.  
  1199.     for(;;) {
  1200.  
  1201.         if (fgets(mp->buf,LineLen,in) == NULL)
  1202.  
  1203.             return 0;
  1204.  
  1205.  
  1206.  
  1207.         if (blank_line_flag)
  1208.  
  1209.             if (strnicmp(mp->buf,pth,5) == 0) {
  1210.  
  1211.                  p = strchr(mp->buf,' ') + 1;
  1212.  
  1213.                  fprintf(out,"%s%s!%s",pth,Host,p);
  1214.  
  1215.                  continue;
  1216.  
  1217.             }
  1218.  
  1219.         /* oh oh - nntpserv is modifying articles....*/
  1220.  
  1221.         if (strlen(mp->buf) == 1 && mp->buf[0] == '.')
  1222.  
  1223.             continue;
  1224.  
  1225.         fputs(mp->buf,out);
  1226.  
  1227.         if(!check_blank(mp->buf))
  1228.  
  1229.             blank_line_flag = 0;
  1230.  
  1231.     }
  1232.  
  1233. }
  1234.  
  1235.  
  1236.  
  1237. /* returncode: < 1 if error; 1 success */
  1238.  
  1239. static int
  1240. dofwd(mp,f,history)
  1241. struct nntpsv *mp;
  1242. FILE *f;
  1243. FILE *history;
  1244.  
  1245. {
  1246.  
  1247.     FILE *fwd;
  1248.  
  1249.  
  1250.  
  1251.     if(mp == NULLNNTPSV)
  1252.  
  1253.         return -1;
  1254.  
  1255.  
  1256.  
  1257.     sprintf(mp->buf,"%s/fwd.seq",Newsdir);
  1258.  
  1259.     if ((fwd = open_file(mp->buf,"r+",mp->s,0)) == NULLFILE)
  1260.  
  1261.         return -1;
  1262.  
  1263.  
  1264.  
  1265.     fgets(mp->buf,LineLen,fwd);
  1266.  
  1267.     mp->hold_i = atoi(mp->buf) + 1;
  1268.  
  1269.     fprintf(history," JUNK/%u",mp->hold_i);
  1270.  
  1271.     rewind(fwd);
  1272.  
  1273.     fprintf(fwd,"%u",mp->hold_i);
  1274.  
  1275.     fclose(fwd);
  1276.  
  1277.  
  1278.  
  1279.     sprintf(mp->buf,"%s/%u",Forward,mp->hold_i);
  1280.  
  1281.     if ((fwd = open_file(mp->buf,WRITE_TEXT,mp->s,0)) == NULLFILE)
  1282.  
  1283.         return -2;
  1284.  
  1285.  
  1286.  
  1287.     rewind(f);
  1288.  
  1289.     dup_f(f,fwd,mp);
  1290.  
  1291.     fclose(fwd);
  1292.  
  1293.     return 1;
  1294.  
  1295. }
  1296.  
  1297.  
  1298.  
  1299. #ifdef CONTROL
  1300.  
  1301. static int
  1302.  
  1303. docontrol(f,mp)
  1304.  
  1305. FILE *f;
  1306.  
  1307. struct nntpsv *mp;
  1308.  
  1309. {
  1310.  
  1311.     struct head *h;
  1312.  
  1313.  
  1314.  
  1315.     if(f == NULLFILE || mp == NULLNNTPSV
  1316.  
  1317.       || (h = (struct head *)callocw(1,sizeof(struct head))) == NULLHEAD))
  1318.  
  1319.         return -1;
  1320.  
  1321.  
  1322.  
  1323.     rewind(f);
  1324.  
  1325.     h->subject = h->from = h->reply_to = h->id = NULLCHAR;
  1326.  
  1327.  
  1328.  
  1329.     for(;;) {
  1330.  
  1331.         if ((fgets(mp->buf,LineLen,f)) == NULL)
  1332.  
  1333.             break;
  1334.  
  1335.         if (check_blank(mp->buf))
  1336.  
  1337.             break;
  1338.  
  1339.         rip2(mp->buf);
  1340.  
  1341.         if (strncmp(mp->buf,subj,9) == 0)
  1342.  
  1343.             h->subject = strdup(mp->buf);
  1344.  
  1345.         if (strncmp(mp->buf,frm,6) == 0)
  1346.  
  1347.             h->from = strdup(mp->buf);
  1348.  
  1349.         if (strnicmp(mp->buf,replyto,10) == 0)
  1350.  
  1351.             h->reply_to = strdup(mp->buf);
  1352.  
  1353.         if (strnicmp(mp->buf,msgid,12) == 0)
  1354.  
  1355.             h->id = strdup(strchr(mp->buf,'<'));
  1356.  
  1357.     }
  1358.  
  1359.     if (h->subject != NULLCHAR)
  1360.  
  1361.         if (strncmp(h->subject,"Subject: sendme ",16) == 0)
  1362.  
  1363.             dosendme(h);
  1364.  
  1365.     if (h->subject != NULLCHAR)
  1366.  
  1367.         free(h->subject);
  1368.  
  1369.     if (h->from != NULLCHAR)
  1370.  
  1371.         free(h->from);
  1372.  
  1373.     if (h->reply_to != NULLCHAR)
  1374.  
  1375.         free(h->reply_to);
  1376.  
  1377.     if (h->id != NULLCHAR)
  1378.  
  1379.         free(h->id);
  1380.  
  1381.     free((char *)h);
  1382.  
  1383.     return 0;
  1384.  
  1385. }
  1386.  
  1387. #endif
  1388.  
  1389.  
  1390.  
  1391. static int
  1392. xfer_article2(f,mp)
  1393. FILE *f;
  1394. struct nntpsv *mp;
  1395.  
  1396. {
  1397.  
  1398.     char line[LineLen], *p, *group = NULLCHAR, *p1, *from = NULLCHAR;
  1399.  
  1400.     FILE *fptr, *history;
  1401.  
  1402.     struct tm *stm;
  1403.  
  1404.     int x;
  1405.  
  1406. #ifdef CONTROL
  1407.  
  1408.     int control = 0;
  1409.  
  1410. #endif
  1411.  
  1412.     long currtime;
  1413.  
  1414.  
  1415.  
  1416.     if(f == NULLFILE || mp == NULLNNTPSV ||
  1417.  
  1418.       (history = open_file(History,APPEND_TEXT,mp->s,0)) == NULLFILE)
  1419.  
  1420.         return -1;
  1421.  
  1422.  
  1423.  
  1424.     for (;;) {
  1425.  
  1426.         if (fgets(line,LineLen,f) == NULL)
  1427.  
  1428.             break;
  1429.  
  1430.         rip2(line);
  1431.  
  1432.         if (strnicmp(line,frm,6) == 0) {
  1433.  
  1434.             p = strchr(line,' ') + 1;
  1435.  
  1436.             from = strdup(p);
  1437.  
  1438.             continue;
  1439.  
  1440.         }
  1441.  
  1442.         if (strnicmp(line,ngrps,12) == 0) {
  1443.  
  1444.             p = strchr(line,' ') + 1;
  1445.  
  1446.             group = strdup(p);
  1447.  
  1448.             break;
  1449.  
  1450.         }
  1451.  
  1452.     }
  1453.  
  1454.     time(&currtime);
  1455.  
  1456.     stm = localtime(&currtime);
  1457.  
  1458.     fprintf(history,"%s %2.2d%2.2d%2.2d %2.2d%2.2d%2.2d",
  1459.  
  1460.         mp->id,
  1461.  
  1462.         stm->tm_year,stm->tm_mon+1,stm->tm_mday,
  1463.  
  1464.         stm->tm_hour,stm->tm_min,stm->tm_sec);
  1465.  
  1466.  
  1467.  
  1468.     mp->hold_i = 0;
  1469.  
  1470.     p = group;
  1471.  
  1472.     if((mp->ap = (struct article *)callocw(1,sizeof(struct article))) == NULLARTICLE)
  1473.  
  1474.         goto quit;
  1475.  
  1476.     x = 1;
  1477.  
  1478.     while (x) {
  1479.  
  1480.         if ((p1 = strchr(p,',')) != NULLCHAR) {
  1481.  
  1482.             p1 = line;
  1483.  
  1484.             while (*p != ',')
  1485.  
  1486.                 *(p1++)=*(p++);
  1487.  
  1488.             *p1 = '\0';
  1489.  
  1490.             p++;
  1491.  
  1492.             mp->ap->group = strdup(line);
  1493.  
  1494.         } else {
  1495.  
  1496.             mp->ap->group = strdup(p);
  1497.  
  1498.             x = 0;
  1499.  
  1500.         }
  1501.  
  1502.         update_list(mp);
  1503.  
  1504.         if (mp->ap->number > 0) {
  1505.  
  1506.             get_path2(mp->ap);
  1507.  
  1508.             mp->hold_i = 1;
  1509.  
  1510.             sprintf(line,"%s/%u",mp->ap->path,mp->ap->number);
  1511.  
  1512.             rewind(f);
  1513.  
  1514.             if ((fptr = open_file(line,WRITE_TEXT,mp->s,0)) == NULLFILE) {
  1515.  
  1516.                 fclose(history);
  1517.  
  1518.                 free(mp->ap->group);
  1519.  
  1520.                 goto quit;
  1521.  
  1522.             }
  1523.  
  1524.             dup_f(f,fptr,mp);
  1525.  
  1526.             fclose(fptr);
  1527.  
  1528.             fprintf(history," %s/%d",mp->ap->group,mp->ap->number);
  1529.  
  1530. #ifdef CONTROL
  1531.  
  1532.             if (strcmp(mp->ap->group,"control") == 0)
  1533.  
  1534.                 control = 1;
  1535.  
  1536. #endif
  1537.  
  1538.             free(mp->ap->path);
  1539.  
  1540.         }
  1541.  
  1542.         free(mp->ap->group);
  1543.  
  1544.     }
  1545.  
  1546.     if (mp->hold_i == 0) {
  1547.  
  1548.         if ((x = dofwd(mp,f,history)) < 1)
  1549.  
  1550.         mp->hold_i = 0;
  1551.  
  1552.     }
  1553.  
  1554.     fputc('\n',history);
  1555.  
  1556.     fclose(history);
  1557.  
  1558.     time(&currtime);
  1559.  
  1560.     if(Nntpquiet < 2)
  1561.  
  1562.         tprintf("New mail in newsgroup %s\n  from <%s> at %s%s",
  1563.  
  1564.             group,from,ctime(&currtime),
  1565.  
  1566.             (Nntpquiet < 1)  ? "\007" : "");
  1567.  
  1568.  
  1569.  
  1570. #ifdef CONTROL
  1571.  
  1572.     if (control == 1)
  1573.  
  1574.         docontrol(f,mp);
  1575.  
  1576. #endif
  1577.  
  1578. quit:
  1579.  
  1580.     free(from);
  1581.  
  1582.     free(group);
  1583.  
  1584.     free((char *)mp->ap);
  1585.  
  1586.     return 1;
  1587.  
  1588. }
  1589.  
  1590.  
  1591.  
  1592. static void
  1593.  
  1594. nntppoll(unused,cb1,p)
  1595.  
  1596. int unused;
  1597.  
  1598. void *cb1;
  1599.  
  1600. void *p;
  1601.  
  1602. {
  1603.  
  1604.     char *cp, line[LineLen];
  1605.  
  1606.     struct sockaddr_in fsocket;
  1607.  
  1608.     struct nntpsv *cb;
  1609.  
  1610.     struct tm *stm, *ltm;
  1611.  
  1612.     FILE *f, *f1, *pf;
  1613.  
  1614.     long t;
  1615.  
  1616.     int r, now, ret;
  1617.  
  1618.     struct Servers *sp = (struct Servers *) cb1;
  1619.  
  1620.     long currtime;
  1621.  
  1622.  
  1623.  
  1624.     if (!run_timer(&sp->nntpt))             /* if timer had stopped there is an
  1625.  
  1626.         return;                                          * active session */
  1627.  
  1628.  
  1629.  
  1630.     if (!Filecheck)
  1631.  
  1632.         if(check_system())
  1633.  
  1634.             return;
  1635.  
  1636.  
  1637.  
  1638. #ifndef UNIX
  1639.  
  1640.     if(availmem() < Memthresh) {
  1641.  
  1642.         start_timer(&sp->nntpt);
  1643.  
  1644.         return;
  1645.  
  1646.     }
  1647.  
  1648. #endif
  1649.  
  1650.  
  1651.  
  1652.     /* check connection window */
  1653.  
  1654.     time(&currtime);
  1655.  
  1656.     ltm = localtime(&currtime);
  1657.  
  1658.     now = ltm->tm_hour * 100 + ltm->tm_min;
  1659.  
  1660.     if (sp->lowtime < sp->hightime) {
  1661.  
  1662.         /* doesn't cross midnight */
  1663.  
  1664.         if (now < sp->lowtime || now >= sp->hightime) {
  1665.  
  1666.             start_timer(&sp->nntpt);
  1667.  
  1668.             return;
  1669.  
  1670.         }
  1671.  
  1672.     } else {
  1673.  
  1674.         if (now < sp->lowtime && now >= sp->hightime) {
  1675.  
  1676.             start_timer(&sp->nntpt);
  1677.  
  1678.             return;
  1679.  
  1680.         }
  1681.  
  1682.     }
  1683.  
  1684.     if((pf = open_file(Poll,"r+",0,1)) == NULLFILE ||
  1685.  
  1686.       (cb = (struct nntpsv *)callocw(1,sizeof(struct nntpsv))) == NULLNNTPSV) {
  1687.  
  1688.         start_timer(&sp->nntpt);
  1689.  
  1690.         return;
  1691.  
  1692.     }
  1693.  
  1694.     stop_timer(&sp->nntpt);
  1695.  
  1696.  
  1697.  
  1698.     cb->fname   = NULLCHAR;
  1699.  
  1700.     cb->newnews = NULLCHAR;
  1701.  
  1702.     rewind(pf);
  1703.  
  1704.  
  1705.  
  1706.     for(t = 0L; fgets(line,LineLen,pf) != NULLCHAR; t = ftell(pf)) {
  1707.  
  1708.         if((cp = strchr(line,' ')) == NULLCHAR)
  1709.  
  1710.             continue;           /* something wrong with this line, skip it */
  1711.  
  1712.         *cp = '\0';
  1713.  
  1714.         if(strnicmp(line,sp->name,strcspn(line," ")-1) == 0) {
  1715.  
  1716.             rip2(cp+1);
  1717.  
  1718.             cb->newnews = strdup(cp+1);
  1719.  
  1720.             /* Prepare to write back the current host and date */
  1721.  
  1722.             fseek(pf,t,0);
  1723.  
  1724.             break;
  1725.  
  1726.         }
  1727.  
  1728.     }
  1729.  
  1730.  
  1731.  
  1732.     if(cb->newnews == NULLCHAR)
  1733.  
  1734.          cb->newnews = strdup("800101 000000");
  1735.  
  1736.  
  1737.  
  1738.     fsocket.sin_family = AF_INET;
  1739.  
  1740.     fsocket.sin_addr.s_addr = cb->dest = sp->dest;
  1741.  
  1742.     fsocket.sin_port = IPPORT_NNTP;
  1743.  
  1744.  
  1745.  
  1746.     if((cb->s = socket(AF_INET,SOCK_STREAM,0)) == -1)
  1747.  
  1748.         goto quit;
  1749.  
  1750.     sockmode(cb->s,SOCK_ASCII);
  1751.  
  1752.  
  1753.  
  1754.     if(connect(cb->s,(char *)&fsocket,SOCKSIZE) == -1)
  1755.  
  1756.         goto quit;
  1757.  
  1758.     log(cb->s,"Connect NNTP");
  1759.  
  1760.  
  1761.  
  1762.     time(&currtime);
  1763.  
  1764.     stm = localtime(&currtime);
  1765.  
  1766.  
  1767.  
  1768.     if(getreply(cb) == -1)          /* throw away any hello msg */
  1769.  
  1770.         goto quit;
  1771.  
  1772.  
  1773.  
  1774.     /* IHAVE preparation */
  1775.  
  1776.     if(NnIhave && (cb->ihave = tmpfile()) != NULLFILE) {
  1777.  
  1778.         sprintf(line,"%s %s",NnIhave == 2 ? "*" : sp->newsgroups,cb->newnews);
  1779.  
  1780.         if(newnews(line,cb,cb->ihave) < 1) {
  1781.  
  1782.             fclose(cb->ihave);
  1783.  
  1784.             cb->ihave = NULLFILE;
  1785.  
  1786.         }
  1787.  
  1788.     }
  1789.  
  1790.  
  1791.  
  1792. #ifdef LZW
  1793.  
  1794.     if (LzwActive)   {
  1795.  
  1796.         usprintf(cb->s,"XLZW %d %d\n",Lzwbits,Lzwmode);
  1797.  
  1798.         if((ret = getreply(cb)) == 235)   {       /* eat negative response */
  1799.  
  1800.             lzwinit(cb->s,Lzwbits,Lzwmode);
  1801.  
  1802.         }
  1803.  
  1804.     }
  1805.  
  1806. #endif
  1807.  
  1808. #ifdef XXX
  1809.  
  1810.     usputs(cb->s,"SLAVE\n");
  1811.  
  1812.     if(getreply(cb) != 202)
  1813.  
  1814.         goto quit;
  1815.  
  1816. #endif
  1817.  
  1818.     cb->slave = 1;
  1819.  
  1820.  
  1821.  
  1822.     if ((f = temp_file(0,1)) == NULLFILE)
  1823.  
  1824.         goto quit;
  1825.  
  1826.  
  1827.  
  1828.     usprintf(cb->s,"NEWNEWS %s %s\n",sp->newsgroups,cb->newnews);
  1829.  
  1830.     if(getreply(cb) != 230) {
  1831.  
  1832.         goto doihave;
  1833.  
  1834.     }
  1835.  
  1836.     if(recv_file(f,cb->s) == -1) {
  1837.  
  1838.         goto doihave;
  1839.  
  1840.     }
  1841.  
  1842.     if ((f1 = temp_file(cb->s,1)) == NULLFILE) {
  1843.  
  1844.         goto doihave;
  1845.  
  1846.     }
  1847.  
  1848.     rewind(f);
  1849.  
  1850.  
  1851.  
  1852.     for(;;) {
  1853.  
  1854.         if (fgets(cb->buf,LineLen,f) == NULL)
  1855.  
  1856.             break;
  1857.  
  1858.         rip2(cb->buf);
  1859.  
  1860.         if (strcmp(cb->buf,".") == 0)
  1861.  
  1862.             break;
  1863.  
  1864.         if (check_article(cb->buf) == 1)
  1865.  
  1866.             continue;
  1867.  
  1868.         usprintf(cb->s,"ARTICLE %s\n",cb->buf);
  1869.  
  1870.         for (;;) {
  1871.  
  1872.             if ((r = recvline(cb->s,cb->buf,LineLen)) == -1)
  1873.  
  1874.                 break;
  1875.  
  1876.             rip2(cb->buf);
  1877.  
  1878.             if(!isdigit(cb->buf[0])) {
  1879.  
  1880.                 r = -1;
  1881.  
  1882.                 continue;
  1883.  
  1884.             } else {
  1885.  
  1886.                 r = atoi(cb->buf);
  1887.  
  1888.                 break;
  1889.  
  1890.             }
  1891.  
  1892.         }
  1893.  
  1894.         if(r == -1)
  1895.  
  1896.             break;
  1897.  
  1898.         if (r == 220) {
  1899.  
  1900.             recv_file(f1,cb->s);
  1901.  
  1902.             rewind(f1);
  1903.  
  1904.             for ( ;; ) {
  1905.  
  1906.                 if (fgets(cb->buf,LineLen,f1) == NULL)
  1907.  
  1908.                     break;
  1909.  
  1910.                 rip2(cb->buf);
  1911.  
  1912.                 if (strnicmp(cb->buf,msgid,12) == 0) {
  1913.  
  1914.                     cb->id = strdup((strchr(cb->buf,' ')) + 1);
  1915.  
  1916.                     break;
  1917.  
  1918.                 }
  1919.  
  1920.             }
  1921.  
  1922.             rewind(f1);
  1923.  
  1924.             xfer_article2(f1,cb);
  1925.  
  1926.             free(cb->id);
  1927.  
  1928.         }
  1929.  
  1930.         fclose(f1);
  1931.  
  1932.         if ((f1 = temp_file(cb->s,1)) == NULLFILE)
  1933.  
  1934.             goto doihave;
  1935.  
  1936.     }
  1937.  
  1938.     fclose(f1);
  1939.  
  1940. doihave:
  1941.  
  1942.     /* IHAVE offer */
  1943.  
  1944.     if(NnIhave && cb->ihave != NULLFILE) {
  1945.  
  1946.         rewind(cb->ihave);
  1947.  
  1948.         while(fgets(line,sizeof(line),cb->ihave),!feof(cb->ihave)) {
  1949.  
  1950.             usprintf(cb->s,"IHAVE %s",line);
  1951.  
  1952.             if((ret = getreply(cb)) == -1)
  1953.  
  1954.                 break;
  1955.  
  1956.             if(ret != 335)
  1957.  
  1958.                 continue;
  1959.  
  1960.             rip2(line);
  1961.  
  1962.             if(doarticle(line,cb) < 1) {
  1963.  
  1964.                 usputs(cb->s,NEol);
  1965.  
  1966.                 if((ret = getreply(cb)) == -1)
  1967.  
  1968.                     break;
  1969.  
  1970.                 continue;
  1971.  
  1972.             }
  1973.  
  1974.             if((ret = getreply(cb)) != 235)
  1975.  
  1976.                 continue;
  1977.  
  1978.         }
  1979.  
  1980.         fclose(cb->ihave);
  1981.  
  1982.     }
  1983.  
  1984.     fclose(f);
  1985.  
  1986.  
  1987.  
  1988. quit:
  1989.  
  1990.     usprintf(cb->s,quitcmd);
  1991.  
  1992.     if (recvline(cb->s,cb->buf,LineLen) == -1);
  1993.  
  1994.  
  1995.  
  1996.     /*
  1997.  
  1998.      * update pollfile
  1999.  
  2000.      */
  2001.  
  2002.     if(errno == 0) {
  2003.  
  2004.         /* Now write back the opening date and time */
  2005.  
  2006.         fprintf(pf,"%s %02d%02d%02d %02d%02d%02d\n",
  2007.  
  2008.             sp->name,
  2009.  
  2010.             stm->tm_year,
  2011.  
  2012.             stm->tm_mon + 1,
  2013.  
  2014.             stm->tm_mday,
  2015.  
  2016.             stm->tm_hour,
  2017.  
  2018.             stm->tm_min,
  2019.  
  2020.             stm->tm_sec);
  2021.  
  2022.     }
  2023.  
  2024.     fclose(pf);
  2025.  
  2026.  
  2027.  
  2028.     close_s(cb->s);
  2029.  
  2030.     free(cb->newnews);
  2031.  
  2032.     free((char *)cb);
  2033.  
  2034.     start_timer(&sp->nntpt);
  2035.  
  2036. }
  2037.  
  2038.  
  2039.  
  2040. static int
  2041. ngmatcha(func,dflt,ngspec,matchlist)
  2042. int     (*func)(char *,char *);
  2043. int     dflt;
  2044. struct g_list *ngspec;
  2045. struct g_list *matchlist;
  2046.  
  2047. {
  2048.  
  2049.     register int    match;
  2050.  
  2051.     char   *cp;
  2052.  
  2053.     struct g_list   *m,*n;
  2054.  
  2055.  
  2056.  
  2057.     match = dflt;
  2058.  
  2059.     m = matchlist;
  2060.  
  2061.     for(;;) {
  2062.  
  2063.         if ((cp = strchr(m->str,'/')) != NULLCHAR)
  2064.  
  2065.             *cp = '\0';
  2066.  
  2067.         n = ngspec;
  2068.  
  2069.         for (;;) {
  2070.  
  2071.             if (n->str[0] == '!') {      /* Handle negation */
  2072.  
  2073.                 if ((*func)(n->str+1, m->str)) {
  2074.  
  2075.                     match = 0;
  2076.  
  2077.                 }
  2078.  
  2079.             } else {
  2080.  
  2081.                 if ((*func)(n->str, m->str)) {
  2082.  
  2083.                     match = 1;
  2084.  
  2085.                 }
  2086.  
  2087.             }
  2088.  
  2089.             if (n->next == NULLG)
  2090.  
  2091.                 break;
  2092.  
  2093.             else
  2094.  
  2095.                 n=n->next;
  2096.  
  2097.         }
  2098.  
  2099.         if (m->next == NULLG)
  2100.  
  2101.             break;
  2102.  
  2103.         else
  2104.  
  2105.             m=m->next;
  2106.  
  2107.     }
  2108.  
  2109.     return (match);
  2110.  
  2111. }
  2112.  
  2113.  
  2114.  
  2115. static int
  2116. restreql(w, s)
  2117. register char *w;
  2118. register char *s;
  2119.  
  2120. {
  2121.  
  2122.     while (*s && *w) {
  2123.  
  2124.         switch (*w) {
  2125.  
  2126.             case '*':
  2127.  
  2128.                 for (w++; *s; s++)
  2129.  
  2130.                     if (restreql(w, s))
  2131.  
  2132.                         return 1;
  2133.  
  2134.                 break;
  2135.  
  2136.             default:
  2137.  
  2138.                 if (*w != *s)
  2139.  
  2140.                     return 0;
  2141.  
  2142.                 w++, s++;
  2143.  
  2144.                 break;
  2145.  
  2146.         }
  2147.  
  2148.     }
  2149.  
  2150.     if (*s)
  2151.  
  2152.         return 0;
  2153.  
  2154.     while (*w)
  2155.  
  2156.         if (*w++ != '*')
  2157.  
  2158.             return 0;
  2159.  
  2160.  
  2161.  
  2162.     return 1;
  2163.  
  2164. }
  2165.  
  2166.  
  2167.  
  2168. /* converts timestring to unix-compatible structure
  2169.  
  2170.  * returncode: 0 (!!) if error; > 0 success */
  2171.  
  2172. static int32
  2173. make_nntime(d,t,str)
  2174. struct date *d;
  2175. struct time *t;
  2176. char *str;
  2177.  
  2178. {
  2179.  
  2180.     register char *cp;
  2181.     char tmp[3];
  2182.     if(str == NULLCHAR)
  2183.         return 0L;
  2184.     tmp[2] = '\0';
  2185.     cp = str;
  2186.     strncpy(tmp,cp,2);
  2187.     d->da_year = atoi(tmp)+1900;
  2188.     if (d->da_year < 1980)
  2189.         d->da_year = 1980;
  2190.     if (d->da_year > 2099)
  2191.         return 0L;
  2192.     cp+=2;
  2193.     strncpy(tmp,cp,2);
  2194.     d->da_mon = atoi(tmp);
  2195.     if (d->da_mon < 1 || d->da_mon > 12)
  2196.         return 0L;
  2197.     cp+=2;
  2198.     strncpy(tmp,cp,2);
  2199.     d->da_day = atoi(tmp);
  2200.     if (d->da_day < 1 || d->da_day > 32)
  2201.         return 0L;
  2202.     cp+=3;
  2203.     strncpy(tmp,cp,2);
  2204.     t->ti_hour = atoi(tmp);
  2205.     if (t->ti_hour >=1 && t->ti_hour <= 23 || t->ti_hour==0){
  2206.         cp+=2;
  2207.         strncpy(tmp,cp,2);
  2208.         t->ti_min = atoi(tmp);
  2209.     }else{
  2210.         return 0L;
  2211.     }
  2212.     if (t->ti_min >= 1 && t->ti_min <= 59 || t->ti_min==0){
  2213.         cp+=2;
  2214.         strncpy(tmp,cp,2);
  2215.         t->ti_sec = atoi(tmp);
  2216.     }else{
  2217.         return 0L;
  2218.     }        
  2219.     if (t->ti_sec >= 1 && t->ti_sec <= 59 || t->ti_sec==0){
  2220.         t->ti_hund = 0;
  2221.         return (dostounix(d,t));
  2222.     }else{
  2223.         return 0L;
  2224.     }
  2225. }
  2226.  
  2227.  
  2228.  
  2229. /* returncode: -1 if error; 0 if no new news; 1 new news available */
  2230.  
  2231. static int
  2232. newnews(string,mp,f)
  2233. char *string;
  2234. struct nntpsv *mp;
  2235. FILE *f;
  2236.  
  2237. {
  2238.  
  2239.     register int i,j;
  2240.  
  2241.     char *cp, *cp1, line[LineLen], groups[LineLen];
  2242.  
  2243.     struct g_list *ng, *hist, *ngp, *histp, *ptr;
  2244.  
  2245.     FILE *f1;
  2246.  
  2247.     int all = 1;
  2248.  
  2249.  
  2250.  
  2251.     if (check_one(string) == -1)
  2252.  
  2253.         return -1;
  2254.  
  2255.  
  2256.  
  2257.     cp = string;
  2258.  
  2259.     i = 1;
  2260.  
  2261.  
  2262.  
  2263.     while (*(cp++) > 32)
  2264.  
  2265.         i++;
  2266.  
  2267.     if (strlen(cp) < 13)
  2268.  
  2269.         return -1;
  2270.  
  2271.  
  2272.  
  2273.     strncpy(groups,string,i-1);
  2274.  
  2275.     groups[i-1] = '\0';
  2276.  
  2277.     if(strcmp(groups,"*") != 0)
  2278.  
  2279.         all = 0;
  2280.  
  2281.  
  2282.  
  2283.     mp->datest = (struct date *)callocw(1,sizeof(struct date));
  2284.  
  2285.     mp->timest = (struct time *)callocw(1,sizeof(struct time));
  2286.  
  2287.     gettime(mp->timest);
  2288.  
  2289.     getdate(mp->datest);
  2290.  
  2291.  
  2292.  
  2293.     if ((mp->unixtime = make_nntime(mp->datest,mp->timest,cp)) == 0)
  2294.  
  2295.         goto quit;
  2296.  
  2297.     if (mp->unixtime == -1L)
  2298.  
  2299.         return 0;
  2300.  
  2301.  
  2302.  
  2303.     if (!all) {
  2304.  
  2305.         ng = ngp = (struct g_list *)callocw(1,(sizeof(struct g_list)));
  2306.  
  2307.         cp = groups;
  2308.  
  2309.  
  2310.  
  2311.         for (;;) {
  2312.  
  2313.             if ((cp1 = strchr(cp,',')) == NULLCHAR ) {
  2314.  
  2315.                 ng->str = strdup(cp);
  2316.  
  2317.                 ng->next = NULLG;
  2318.  
  2319.                 break;
  2320.  
  2321.             }
  2322.  
  2323.             j = strcspn(cp,",");
  2324.  
  2325.             ng->str = (char *)callocw(1,j+1);
  2326.  
  2327.             strncpy(ng->str,cp,j);
  2328.  
  2329.             ng->str[j] = '\0';
  2330.  
  2331.             ng->next = (struct g_list *)callocw(1,sizeof(struct g_list));
  2332.  
  2333.             ng = ng->next;
  2334.  
  2335.             cp1 = strchr(cp,',');
  2336.  
  2337.             if (cp1 != NULLCHAR)
  2338.  
  2339.                 cp = cp1 + 1;
  2340.  
  2341.             else
  2342.  
  2343.                 break;
  2344.  
  2345.         }
  2346.  
  2347.     }
  2348.  
  2349.  
  2350.  
  2351.     if ((f1 = open_file(History,READ_TEXT,mp->s,0)) == NULLFILE)
  2352.  
  2353.         goto quit;
  2354.  
  2355.  
  2356.  
  2357.     for (;;) {
  2358.  
  2359.         if (fgets(line,LineLen,f1) == NULL)
  2360.  
  2361.             break;
  2362.  
  2363.         rip2(line);
  2364.  
  2365.  
  2366.  
  2367.         if (!all) {
  2368.  
  2369.             for(i = 3, cp = line; i; --i)
  2370.  
  2371.                 cp = strchr(cp,' ') + 1;
  2372.  
  2373.             histp = (struct g_list *)callocw(1,sizeof(struct g_list));
  2374.  
  2375.             hist = histp;
  2376.  
  2377.  
  2378.  
  2379.             for (;;) {
  2380.  
  2381.                 if ((cp1 = strchr(cp,' ')) == NULLCHAR) {
  2382.  
  2383.                     hist->str = strdup(cp);
  2384.  
  2385.                     hist->next = NULLG;
  2386.  
  2387.                     break;
  2388.  
  2389.                 }
  2390.  
  2391.  
  2392.  
  2393.                 j = strcspn(cp," ");
  2394.  
  2395.                 hist->str = (char *)callocw(1,j+1);
  2396.  
  2397.                 strncpy(hist->str,cp,j);
  2398.  
  2399.                 hist->str[j] = '\0';
  2400.  
  2401.                 hist->next = (struct g_list *)callocw(1,sizeof(struct g_list));
  2402.  
  2403.                 hist = hist->next;
  2404.  
  2405.                 cp1 = strchr(cp,' ');
  2406.  
  2407.                 if (cp1 != NULLCHAR)
  2408.  
  2409.                     cp = cp1 + 1;
  2410.  
  2411.                 else
  2412.  
  2413.                     break;
  2414.  
  2415.             }
  2416.  
  2417.             if (!ngmatcha(restreql,0,ngp,histp)) {
  2418.  
  2419.                 ptr = histp;
  2420.  
  2421.                     for (;;) {
  2422.  
  2423.                         ptr = histp->next;
  2424.  
  2425.                         free(histp->str);
  2426.  
  2427.                         free(histp);
  2428.  
  2429.                         histp = ptr;
  2430.  
  2431.                         if (histp == NULLG)
  2432.  
  2433.                             break;
  2434.  
  2435.                     }
  2436.  
  2437.                 continue;
  2438.  
  2439.             }
  2440.  
  2441.         }
  2442.  
  2443.         cp = strchr(line,' ') + 1;
  2444.  
  2445.         if ((mp->ftime = make_nntime(mp->datest,mp->timest,cp)) == 0) {
  2446.  
  2447.             fclose(f1);
  2448.  
  2449.             goto quit;
  2450.  
  2451.         }
  2452.  
  2453.         if ((mp->ftime - mp->unixtime) > 0) {
  2454.  
  2455.             cp = line;
  2456.  
  2457.             while ( *cp > 32 )
  2458.  
  2459.                 fputc(*(cp++),f);
  2460.  
  2461.             fputc('\n',f);
  2462.  
  2463.         }
  2464.  
  2465.         if (!all) {
  2466.  
  2467.             ptr = histp;
  2468.  
  2469.             for (;;) {
  2470.  
  2471.                 ptr = histp->next;
  2472.  
  2473.                 free(histp->str);
  2474.  
  2475.                 free(histp);
  2476.  
  2477.                 histp = ptr;
  2478.  
  2479.                 if (histp == NULLG)
  2480.  
  2481.                     break;
  2482.  
  2483.             }
  2484.  
  2485.         }
  2486.  
  2487.     }
  2488.  
  2489.     fclose(f1);
  2490.  
  2491.     if (!all) {
  2492.  
  2493.         ptr = ngp;
  2494.  
  2495.         for (;;) {
  2496.  
  2497.             ptr = ngp->next;
  2498.  
  2499.             free(ngp->str);
  2500.  
  2501.             free(ngp);
  2502.  
  2503.             ngp = ptr;
  2504.  
  2505.             if (ngp == NULLG)
  2506.  
  2507.                 break;
  2508.  
  2509.         }
  2510.  
  2511.     }
  2512.  
  2513.     free(mp->datest);
  2514.  
  2515.     free(mp->timest);
  2516.  
  2517.     return 1;
  2518.  
  2519. quit:
  2520.  
  2521.     return 0;
  2522.  
  2523. }
  2524.  
  2525.  
  2526.  
  2527. /* handles incoming newnews-cmd
  2528.  
  2529.  * returncode: -1 if error; 0 no groups or bad syntax; 1 success */
  2530.  
  2531. static int
  2532. donewnews(string,mp)
  2533. char *string;
  2534. struct nntpsv *mp;
  2535.  
  2536. {
  2537.  
  2538.     FILE *f;
  2539.  
  2540.     int ret;
  2541.  
  2542.  
  2543.  
  2544.     if((f = temp_file(mp->s,1)) == NULLFILE)
  2545.  
  2546.         return -1;
  2547.  
  2548.  
  2549.  
  2550.     ret = newnews(string,mp,f);
  2551.  
  2552.  
  2553.  
  2554.     switch(ret) {
  2555.  
  2556.     case -1:                                                /* error in "newnews" routine */
  2557.  
  2558.         ret = 0;
  2559.  
  2560.         usputs(mp->s,badsyntax);
  2561.  
  2562.         break;
  2563.  
  2564.     case 0:                         /* no new news */
  2565.  
  2566.         usputs(mp->s,newnews_t);
  2567.  
  2568.         usputs(mp->s,NEol);
  2569.  
  2570.         break;
  2571.  
  2572.     default:                                                /* new news available, send news file */
  2573.  
  2574.         rewind(f);
  2575.  
  2576.         usputs(mp->s,newnews_t);
  2577.  
  2578.         sendfile(f,mp->s,ASCII_TYPE,0);
  2579.  
  2580.         usputs(mp->s,NEol);
  2581.  
  2582.         ret = 1;
  2583.  
  2584.         break;
  2585.  
  2586.     }
  2587.  
  2588.     fclose(f);
  2589.  
  2590.     return ret;
  2591.  
  2592. }
  2593.  
  2594.  
  2595.  
  2596. /* change current newsgroup
  2597.  
  2598.  * returncode: -1 if error; 0 success; 1 no newsgroup */
  2599.  
  2600. static int
  2601. dogroup(mp,buf)
  2602. struct nntpsv *mp;
  2603. char *buf;
  2604.  
  2605. {
  2606.  
  2607.     char *p;
  2608.  
  2609.     int er;
  2610.  
  2611.  
  2612.  
  2613.     if((p = strchr(buf,' ')) == NULLCHAR)
  2614.  
  2615.         return -1;
  2616.  
  2617.  
  2618.  
  2619.     er = get_path(p,mp);
  2620.  
  2621.  
  2622.  
  2623.     switch (er) {
  2624.  
  2625.     case 0:
  2626.  
  2627.         usputs(mp->s,nogroup);
  2628.  
  2629.         return 1;
  2630.  
  2631.     default:
  2632.  
  2633.         p = strchr(buf,' ');
  2634.  
  2635.         if (get_pointer(p,mp) == 1) {
  2636.  
  2637.             usprintf(mp->s,listarticle,
  2638.  
  2639.                 mp->last - mp->first + 1,mp->first,mp->last,strchr(buf,' '));
  2640.  
  2641.             return 0;
  2642.  
  2643.         }
  2644.  
  2645.     case -1:
  2646.  
  2647.         usputs(mp->s,error);
  2648.  
  2649.         return -1;
  2650.  
  2651.     }
  2652.  
  2653. }
  2654.  
  2655.  
  2656.  
  2657.  
  2658.  
  2659. /* checks if newsgroup is selected
  2660.  
  2661.  * returncode: -1 no group selected; 0 success */
  2662.  
  2663. static int
  2664. check_grp(mp)
  2665. struct nntpsv *mp;
  2666.  
  2667. {
  2668.  
  2669.     if(mp == NULLNNTPSV || mp->path == NULLCHAR) {
  2670.  
  2671.         usputs(mp->s,noselect);
  2672.  
  2673.         return -1;
  2674.  
  2675.     }
  2676.  
  2677.     return 0;
  2678.  
  2679. }
  2680.  
  2681.  
  2682.  
  2683. /* get id-number of message
  2684.  
  2685.  * returncode: -1 if error; 0 if no message; 1 success */
  2686.  
  2687. static int
  2688. get_id(bp,mp)
  2689. char *bp;
  2690. struct nntpsv *mp;
  2691.  
  2692. {
  2693.  
  2694.     FILE *f;
  2695.  
  2696.     char tmp[LineLen];
  2697.  
  2698.  
  2699.  
  2700.     if ((f = open_message(mp,NULLFILE)) == NULLFILE)
  2701.  
  2702.         return 0;
  2703.  
  2704.  
  2705.  
  2706.     for (;;) {
  2707.  
  2708.         if (fgets(tmp,LineLen,f) == NULL)
  2709.  
  2710.             break;
  2711.  
  2712.         if (check_blank(tmp))
  2713.  
  2714.             break;
  2715.  
  2716.         if (strnicmp(tmp,msgid,12)==0) {
  2717.  
  2718.             fclose(f);
  2719.  
  2720.             strcpy(bp,strchr(tmp,' '));
  2721.  
  2722.             rip2(bp);
  2723.  
  2724.             return 1;
  2725.  
  2726.         }
  2727.  
  2728.     }
  2729.  
  2730.     fclose(f);
  2731.  
  2732.     strcpy(bp,"\0");
  2733.  
  2734.     return 0;
  2735.  
  2736. }
  2737.  
  2738.  
  2739.  
  2740. /* gets next news of newsgroup
  2741.  
  2742.  * returncode: -1 if error; 0 no news; 1 success */
  2743.  
  2744. static int
  2745. get_next(mp)
  2746. struct nntpsv *mp;
  2747.  
  2748. {
  2749.  
  2750.     FILE *f;
  2751.  
  2752.  
  2753.  
  2754.     for (;;) {
  2755.  
  2756.         if (mp->pointer == 0 ) {
  2757.  
  2758.             usputs(mp->s,nonext);
  2759.  
  2760.             return 0;
  2761.  
  2762.         }
  2763.  
  2764.         if (++(mp->pointer) > mp->last) {
  2765.  
  2766.             mp->pointer--;
  2767.  
  2768.             usputs(mp->s,nonext);
  2769.  
  2770.             return 0;
  2771.  
  2772.         }
  2773.  
  2774.         sprintf(mp->buf,"%s/%u",mp->path,mp->pointer);
  2775.  
  2776.         if ((f = open_file(mp->buf,READ_TEXT,mp->s,0)) != NULLFILE) {
  2777.  
  2778.             fclose(f);
  2779.  
  2780.             return 1;
  2781.  
  2782.         }
  2783.  
  2784.     }
  2785.  
  2786. }
  2787.  
  2788.  
  2789.  
  2790. /* gets last news of newsgroup
  2791.  
  2792.  * returncode: -1 if error; 0 no news; 1 success */
  2793.  
  2794. static int
  2795. get_last(mp)
  2796. struct nntpsv *mp;
  2797.  
  2798. {
  2799.  
  2800.     FILE *f;
  2801.  
  2802.  
  2803.  
  2804.     for (;;) {
  2805.  
  2806.         if (mp->pointer == 0) {
  2807.  
  2808.             usputs(mp->s,noprev);
  2809.  
  2810.             return 0;
  2811.  
  2812.         }
  2813.  
  2814.         if (--(mp->pointer) < mp->first) {
  2815.  
  2816.             mp->pointer++;
  2817.  
  2818.             usputs(mp->s,noprev);
  2819.  
  2820.             return 0;
  2821.  
  2822.         }
  2823.  
  2824.         sprintf(mp->buf,"%s/%u",mp->path,mp->pointer);
  2825.  
  2826.         if ((f = open_file(mp->buf,READ_TEXT,mp->s,0)) != NULLFILE) {
  2827.  
  2828.             fclose(f);
  2829.  
  2830.             return 1;
  2831.  
  2832.         }
  2833.  
  2834.     }
  2835.  
  2836. }
  2837.  
  2838.  
  2839.  
  2840. static int
  2841. art_ret(mp)
  2842. struct nntpsv *mp;
  2843.  
  2844. {
  2845.  
  2846.     if(get_id(mp->buf,mp) == -1)
  2847.  
  2848.         return -1;
  2849.  
  2850.     return usprintf(mp->s,retrieve,mp->pointer,mp->buf,artmsg);
  2851.  
  2852. }
  2853.  
  2854.  
  2855.  
  2856. static int
  2857. doarticle(buf,mp)   /* Sends article <message-id> to the client */
  2858. char *buf;
  2859. struct nntpsv *mp;
  2860.  
  2861. {
  2862.  
  2863.     FILE *f;
  2864.  
  2865.     char *p, *p2, *holds, line[LineLen];
  2866.  
  2867.  
  2868.  
  2869.     if((p = strchr(buf,'<')) == NULLCHAR
  2870.  
  2871.      || (f = open_file(History,READ_TEXT,mp->s,0)) == NULLFILE)
  2872.  
  2873.         return 0;
  2874.  
  2875.  
  2876.  
  2877.     for(;;) {
  2878.  
  2879.         if (fgets(line,LineLen,f) == NULL)
  2880.  
  2881.             break;
  2882.  
  2883.         if (strstr(line,p) != NULL) {
  2884.  
  2885.             fclose(f);
  2886.  
  2887.  
  2888.  
  2889.             p = (strchr(line,' ')) + 14;    /* point to the first newsgroup */
  2890.  
  2891.             p2 = strchr(p,'/');                             /* point to article number */
  2892.  
  2893.             mp->hold_i = mp->pointer;       /* save current pointer */
  2894.  
  2895.             holds = strdup(mp->path);      /* save path of current article */
  2896.  
  2897.             mp->pointer = atoi((p2 + 1));   /* get the article number */
  2898.  
  2899.  
  2900.  
  2901.             if (mp->path != NULLCHAR) {
  2902.  
  2903.                 free(mp->path);
  2904.  
  2905.                 mp->path='\0';
  2906.  
  2907.             }
  2908.  
  2909.  
  2910.  
  2911.             *p2 = '\0';
  2912.  
  2913.             rip2(p);
  2914.  
  2915.  
  2916.  
  2917.             if (strncmp(p+1,"JUNK",6) == 0) {
  2918.  
  2919.                 sprintf(mp->buf,"%s",Forward);
  2920.  
  2921.                 mp->path = strdup(mp->buf);
  2922.  
  2923.             } else
  2924.  
  2925.                 get_path(p,mp);
  2926.  
  2927.  
  2928.  
  2929.             if ((f = open_message(mp,f)) == NULLFILE) {
  2930.  
  2931.                 usputs(mp->s,error);
  2932.  
  2933.                 return 0;
  2934.  
  2935.             }
  2936.  
  2937.             art_ret(mp);
  2938.  
  2939.             sendfile(f, mp->s, ASCII_TYPE,0);
  2940.  
  2941.             fclose(f);
  2942.  
  2943.             usputs(mp->s,NEol);
  2944.  
  2945.             free(mp->path);
  2946.  
  2947.             mp->path=strdup(holds);
  2948.  
  2949.             mp->pointer=mp->hold_i;
  2950.  
  2951.             free(holds);
  2952.  
  2953.             return 1;
  2954.  
  2955.         }
  2956.  
  2957.  
  2958.  
  2959.     }
  2960.  
  2961.     fclose(f);
  2962.  
  2963.     usputs(mp->s,noart);
  2964.  
  2965.     return 0;
  2966.  
  2967. }
  2968.  
  2969.  
  2970.  
  2971. /* checks for a minimum header
  2972.  
  2973.  * returncode: -1 if error; 0 complete; 1 not complete */
  2974.  
  2975. static int
  2976. garbled(f)
  2977. FILE *f;
  2978.  
  2979. {
  2980.  
  2981. /*
  2982.  
  2983.  * The minimum requirement for an incoming article is that it must have
  2984.  
  2985.  * a newsgroups: line, a message-id: line, and a blank line.  This is
  2986.  
  2987.  * pretty forgiving.
  2988.  
  2989.  */
  2990.  
  2991.     char line[LineLen];
  2992.  
  2993.     int ok = 0;
  2994.  
  2995.  
  2996.  
  2997.     rewind(f);
  2998.  
  2999.     for(;;) {
  3000.  
  3001.         if (fgets(line,LineLen,f) == NULL)
  3002.  
  3003.             break;
  3004.  
  3005.         if (strnicmp(line,ngrps,12) == 0)
  3006.  
  3007.             ok |= 1;
  3008.  
  3009.         if (strnicmp(line,msgid,12) == 0)
  3010.  
  3011.             ok |= 2;
  3012.  
  3013.         if (ok == 3)
  3014.  
  3015.             break;
  3016.  
  3017.         if (check_blank(line))
  3018.  
  3019.             break;
  3020.  
  3021.     }
  3022.  
  3023.     rewind(f);
  3024.  
  3025.     return (ok == 3) ? 0 : 1;
  3026.  
  3027. }
  3028.  
  3029.  
  3030.  
  3031. /* returncode: -1 if error; 0 success */
  3032.  
  3033. static int
  3034. get_article2(mp, id)
  3035. struct nntpsv *mp;
  3036. char *id;
  3037.  
  3038. {
  3039.  
  3040.     FILE *f;
  3041.  
  3042.     int ret = -1;
  3043.  
  3044.  
  3045.  
  3046.     if((f = temp_file(0,1)) == NULLFILE)
  3047.  
  3048.         return -1;
  3049.  
  3050.  
  3051.  
  3052.     mp->ap = (struct article *)callocw(1,sizeof(struct article));
  3053.  
  3054.     mp->id = (*id) ? strdup(id) : strdup(">");
  3055.  
  3056.     usputs(mp->s,sendart);
  3057.  
  3058.  
  3059.  
  3060.     if(recv_file(f,mp->s) == (-1)) {
  3061.  
  3062.         free((struct article *)mp->ap);
  3063.  
  3064.         goto quit;
  3065.  
  3066.         }
  3067.  
  3068.     if ((ret = garbled(f)) != 0) {
  3069.  
  3070.         usputs(mp->s,transnotok);
  3071.  
  3072.         free((struct article *)mp->ap);
  3073.  
  3074.         goto quit;
  3075.  
  3076.         }
  3077.  
  3078.     if(xfer_article2(f,mp) == 0)
  3079.  
  3080.         goto quit;
  3081.  
  3082.     usputs(mp->s,transok);
  3083.  
  3084.  
  3085.  
  3086. quit:
  3087.  
  3088.     fclose(f);
  3089.  
  3090.     return ret;
  3091.  
  3092. }
  3093.  
  3094.  
  3095.  
  3096. void
  3097. poll(p)
  3098. void *p;
  3099.  
  3100. {
  3101.  
  3102.     newproc("NNTP Client", 2048, nntppoll, 0, p, NULL, 0);
  3103.  
  3104. }
  3105.  
  3106.  
  3107.  
  3108. static void
  3109.  
  3110. nntpserv(s,unused,p)
  3111.  
  3112. int s;
  3113.  
  3114. void *unused;
  3115.  
  3116. void *p;
  3117.  
  3118. {
  3119.  
  3120.     struct nntpsv *mp;
  3121.  
  3122.     FILE *fp;
  3123.  
  3124.     long t;
  3125.  
  3126.     int cnt;
  3127.  
  3128.     char **cmdp, *arg, *cp, *cmd, buf[LineLen];
  3129.  
  3130. #ifdef LZW
  3131.  
  3132.     int lbits, lmode;
  3133.  
  3134. #endif
  3135.  
  3136.  
  3137.  
  3138.     sockmode(s,SOCK_ASCII);
  3139.  
  3140.     sockowner(s,Curproc);           /* We own it now */
  3141.  
  3142.     log(s,"open NNTP");
  3143.  
  3144.  
  3145.  
  3146.     if (!Filecheck)
  3147.  
  3148.         if(check_system()) {
  3149.  
  3150.             usprintf(s,fatal,"STRUCTURE");
  3151.  
  3152.             log(s,"NNTP error - FILE STRU");
  3153.  
  3154.             close_s(s);
  3155.  
  3156.             return;
  3157.  
  3158.         }
  3159.  
  3160.     if((mp = (struct nntpsv *)callocw(1,sizeof(struct nntpsv))) == NULLNNTPSV) {
  3161.  
  3162.         usprintf(s,Nospace);
  3163.  
  3164.         close_s(s);
  3165.  
  3166.         return;
  3167.  
  3168.     }
  3169.  
  3170.     mp->s = s;
  3171.  
  3172.     mp->debug = 0;
  3173.  
  3174.     mp->path = NULLCHAR;
  3175.  
  3176.  
  3177.  
  3178.     time(&t);
  3179.  
  3180.     cp = ctime(&t);
  3181.  
  3182.     cp[24] = '\0';
  3183.  
  3184.  
  3185.  
  3186.     usprintf(s,nnversion,(Filecheck) ? "0" : "1",Host,Version,cp);
  3187.  
  3188.  
  3189.  
  3190. loop:
  3191.  
  3192.     if ((cnt = recvline(s,buf,LineLen)) == -1) {
  3193.  
  3194.         /* He closed on us */
  3195.  
  3196.         goto quit;
  3197.  
  3198.     }
  3199.  
  3200.     rip2(buf);
  3201.  
  3202.     cmd = buf;
  3203.  
  3204.  
  3205.  
  3206.     /* Translate entire buffer to lower case */
  3207.  
  3208.     for(cp = cmd; *cp != '\0' ;cp++) {
  3209.  
  3210.         if ( *cp == ' ' ) break;
  3211.  
  3212.         *cp = tolower(*cp);
  3213.  
  3214.     }
  3215.  
  3216.     /* Find command in table; if not present, return syntax error */
  3217.  
  3218.     for(cmdp = commands; *cmdp != NULLCHAR; cmdp++)
  3219.  
  3220.         if(strnicmp(*cmdp,cmd,min(strlen(*cmdp),strlen(cmd))) == 0)
  3221.  
  3222.             break;
  3223.  
  3224.  
  3225.  
  3226.     if(*cmdp == NULLCHAR){
  3227.  
  3228.         usputs(mp->s,badsyntax);
  3229.  
  3230.         goto loop;
  3231.  
  3232.     }
  3233.  
  3234.     arg = &cmd[strlen(*cmdp)];
  3235.  
  3236.  
  3237.  
  3238.     /* Skip spaces after command */
  3239.  
  3240.     while(*arg == ' ')
  3241.  
  3242.         arg++;
  3243.  
  3244.  
  3245.  
  3246.     /* Execute specific command */
  3247.  
  3248.     switch(cmdp - commands) {
  3249.  
  3250.     case XLZW_CMD:
  3251.  
  3252. #ifdef LZW
  3253.  
  3254.         if (LzwActive)   {
  3255.  
  3256.             usprintf(mp->s,transok);
  3257.  
  3258.             cp = strchr(arg,' ');
  3259.  
  3260.             *cp++ = '\0';
  3261.  
  3262.             lbits = atoi(arg); /*get lzwbits*/
  3263.  
  3264.             lmode = atoi(cp);
  3265.  
  3266.             lzwinit(mp->s,lbits,lmode);
  3267.  
  3268.         } else
  3269.  
  3270. #endif
  3271.  
  3272.             usprintf(mp->s,error);
  3273.  
  3274.         break;
  3275.  
  3276.     case QUIT_CMD:
  3277.  
  3278.         goto quit;
  3279.  
  3280.     case NEWNEWS_CMD:
  3281.  
  3282.         if ((cp = strchr(buf,' ')) == NULLCHAR) {
  3283.  
  3284.             usputs(mp->s,badsyntax);
  3285.  
  3286.             break;
  3287.  
  3288.         }
  3289.  
  3290.         cp++;
  3291.  
  3292.         donewnews(cp,mp);
  3293.  
  3294.         break;
  3295.  
  3296.     case IHAVE_CMD:
  3297.  
  3298.         if ((cp = strchr(buf,'<')) == NULLCHAR) {
  3299.  
  3300.             usputs(mp->s,badsyntax);
  3301.  
  3302.             break;
  3303.  
  3304.         }
  3305.  
  3306.         if (check_article(cp) == 1) {
  3307.  
  3308.             usputs(mp->s,notwanted);
  3309.  
  3310.             break;
  3311.  
  3312.         }
  3313.  
  3314.         if(get_article2(mp,cp))
  3315.  
  3316.             goto quit;
  3317.  
  3318.         break;
  3319.  
  3320.     case HELP_CMD:
  3321.  
  3322.         usprintf(mp->s,"100 %s - help follows:\n",Host);
  3323.  
  3324.         if ((fp = open_file(Nhelp,READ_TEXT,0,0)) != NULLFILE ) {
  3325.  
  3326.             sendfile(fp,mp->s,ASCII_TYPE,0);
  3327.  
  3328.             fclose(fp);
  3329.  
  3330.         } else {
  3331.  
  3332.             usputs(mp->s,help);
  3333.  
  3334.         }
  3335.  
  3336.         usputs(mp->s,NEol);
  3337.  
  3338.         break;
  3339.  
  3340.     case XINFO_CMD:
  3341.  
  3342.         if ((fp = open_file(NInfo,READ_TEXT,0,0)) != NULLFILE ) {
  3343.  
  3344.             usprintf(mp->s,"100 %s - xinfo follows:\n",Host);
  3345.  
  3346.             sendfile(fp,mp->s,ASCII_TYPE,0);
  3347.  
  3348.             fclose(fp);
  3349.  
  3350.         } else {
  3351.  
  3352.             usputs(mp->s,xinfo);
  3353.  
  3354.         }
  3355.  
  3356.         usputs(mp->s,NEol);
  3357.  
  3358.         break;
  3359.  
  3360.     case LIST_CMD:
  3361.  
  3362.         if ((fp = open_file(Active,READ_TEXT,mp->s,0)) != NULLFILE) {
  3363.  
  3364.             sendfile(fp,mp->s,ASCII_TYPE,0);
  3365.  
  3366.             fclose(fp);
  3367.  
  3368.             usputs(mp->s,NEol);
  3369.  
  3370.         }
  3371.  
  3372.         break;
  3373.  
  3374.     case GROUP_CMD :
  3375.  
  3376.         dogroup(mp,&buf[0]);
  3377.  
  3378.         break;
  3379.  
  3380.     case HEAD_CMD : {
  3381.  
  3382.         if (check_grp(mp))
  3383.  
  3384.             break;
  3385.  
  3386.         if (get_id(mp->buf,mp) == 0)
  3387.  
  3388.             break;
  3389.  
  3390.         usprintf(mp->s,head,mp->pointer,mp->buf,artmsg);
  3391.  
  3392.         if ((fp = open_message(mp,fp)) == NULLFILE)
  3393.  
  3394.             break;
  3395.  
  3396.         for (;;) {
  3397.  
  3398.             if ((fgets(mp->buf,LineLen,fp)) == NULL)
  3399.  
  3400.                 break;
  3401.  
  3402.             if (check_blank(mp->buf))
  3403.  
  3404.                 break;
  3405.  
  3406.             usprintf(mp->s,"%s",mp->buf);
  3407.  
  3408.         }
  3409.  
  3410.         fclose(fp);
  3411.  
  3412.         usputs(mp->s,NEol);
  3413.  
  3414.         break;
  3415.  
  3416.     }
  3417.  
  3418.     case BODY_CMD : {
  3419.  
  3420.         if (check_grp(mp))
  3421.  
  3422.             break;
  3423.  
  3424.         if (get_id(mp->buf,mp) == 0)
  3425.  
  3426.             break;
  3427.  
  3428.         usprintf(mp->s,body,mp->pointer,mp->buf,artmsg);
  3429.  
  3430.         if ((fp = open_message(mp,fp)) == NULLFILE)
  3431.  
  3432.             break;
  3433.  
  3434.         mp->hold_i = 0;
  3435.  
  3436.         for (;;) {
  3437.  
  3438.             if ((fgets(mp->buf,LineLen,fp)) == NULL)
  3439.  
  3440.                 break;
  3441.  
  3442.             if (mp->hold_i)
  3443.  
  3444.                 usputs(mp->s,mp->buf);
  3445.  
  3446.             if (check_blank(mp->buf))
  3447.  
  3448.                 mp->hold_i = 1;
  3449.  
  3450.         }
  3451.  
  3452.         fclose(fp);
  3453.  
  3454.         usputs(mp->s,NEol);
  3455.  
  3456.         break;
  3457.  
  3458.     }
  3459.  
  3460.     case STAT_CMD : {
  3461.  
  3462.         if (check_grp(mp))
  3463.  
  3464.             break;
  3465.  
  3466.         if (get_id(mp->buf,mp) == 0)
  3467.  
  3468.             break;
  3469.  
  3470.         usprintf(mp->s,statistics,mp->pointer,mp->buf,artmsg);
  3471.  
  3472.         break;
  3473.  
  3474.     }
  3475.  
  3476.     case ARTICLE_CMD : {
  3477.  
  3478.         if (strchr(buf,'<') != NULLCHAR) {
  3479.  
  3480.           doarticle(buf,mp);
  3481.  
  3482.           break;
  3483.  
  3484.         }
  3485.  
  3486.         if (check_grp(mp))
  3487.  
  3488.             break;
  3489.  
  3490.         cp = strchr(buf,'e');
  3491.  
  3492.         cp++;
  3493.  
  3494.         if ((cnt < 9 ) || (check_blank(cp))) {
  3495.  
  3496.             if ((fp = open_message(mp,fp)) == NULLFILE)
  3497.  
  3498.                 break;
  3499.  
  3500.             art_ret(mp);
  3501.  
  3502.             sendfile(fp,mp->s,ASCII_TYPE,0);
  3503.  
  3504.             fclose(fp);
  3505.  
  3506.             usputs(mp->s,NEol);
  3507.  
  3508.             break;
  3509.  
  3510.         }
  3511.  
  3512.         if ((cp = strpbrk(buf,"0123456789")) != NULLCHAR) {
  3513.  
  3514.             cnt = atoi(cp);
  3515.  
  3516.             if ((cnt > mp->last) || ( cnt < mp->first)) {
  3517.  
  3518.                 usputs(mp->s,noart);
  3519.  
  3520.                 break;
  3521.  
  3522.             }
  3523.  
  3524.             mp->pointer = cnt;
  3525.  
  3526.             if ((fp = open_message(mp,fp)) == NULLFILE)
  3527.  
  3528.                 break;
  3529.  
  3530.             art_ret(mp);
  3531.  
  3532.             sendfile(fp,mp->s,ASCII_TYPE,0);
  3533.  
  3534.             fclose(fp);
  3535.  
  3536.             usputs(mp->s,NEol);
  3537.  
  3538.             break;
  3539.  
  3540.         }
  3541.  
  3542.         break;
  3543.  
  3544.     }
  3545.  
  3546.     case NEXT_CMD : {
  3547.  
  3548.         if (check_grp(mp))
  3549.  
  3550.             break;
  3551.  
  3552.         if (get_next(mp) == 1) {
  3553.  
  3554.             if (get_id(buf,mp) == 1)
  3555.  
  3556.                 usprintf(mp->s,sepcmd,mp->pointer,&buf[1],artmsg);
  3557.  
  3558.             break;
  3559.  
  3560.         }
  3561.  
  3562.         break;
  3563.  
  3564.     }
  3565.  
  3566.     case LAST_CMD :
  3567.  
  3568.         if (check_grp(mp))
  3569.  
  3570.             break;
  3571.  
  3572.         if (get_last(mp) == 1 ) {
  3573.  
  3574.             if (get_id(buf,mp) == 1)
  3575.  
  3576.                 usprintf(mp->s,sepcmd,mp->pointer,&buf[1],artmsg);
  3577.  
  3578.             break;
  3579.  
  3580.         }
  3581.  
  3582.         break;
  3583.  
  3584.     /* This two following cmds currently are not used for much */
  3585.  
  3586.     case DEBUG_CMD:
  3587.  
  3588.         mp->debug = (mp->debug == 0) ? 1 : 0;
  3589.  
  3590.         usprintf(mp->s,debug,(mp->debug == 0) ? "OFF" : "ON");
  3591.  
  3592.         break;
  3593.  
  3594.     case SLAVE_CMD :
  3595.  
  3596.         mp->slave = (mp->slave == 0) ? 1 : 0;
  3597.  
  3598.         usprintf(mp->s,slave,(mp->slave == 0) ? "OFF" : "ON");
  3599.  
  3600.         break;
  3601.  
  3602.     }
  3603.  
  3604.     goto loop;
  3605.  
  3606.  
  3607.  
  3608. quit:
  3609.  
  3610.     usputs(mp->s,closing);
  3611.  
  3612.     log(mp->s,"close NNTP");
  3613.  
  3614.     close_s(mp->s);
  3615.  
  3616.     if(mp->path != NULLCHAR)
  3617.  
  3618.         free(mp->path);
  3619.  
  3620.     if(mp->newnews != NULLCHAR)
  3621.  
  3622.         free(mp->newnews);
  3623.  
  3624.     if(mp->fname != NULLCHAR)
  3625.  
  3626.         free(mp->fname);
  3627.  
  3628.     if(mp->id != NULLCHAR);
  3629.  
  3630.         free(mp->id);
  3631.  
  3632.     free((char *)mp);
  3633.  
  3634. }
  3635.  
  3636.  
  3637.  
  3638. /* ---------------------------- NNTP-GATE --------------------------- */
  3639.  
  3640.  
  3641.  
  3642. static char * near
  3643.  
  3644. mkreplypath(FILE *data)
  3645.  
  3646. {
  3647.  
  3648.     char buf[LINELEN], *cp, *cp1, *path;
  3649.  
  3650.  
  3651.  
  3652.     sprintf(buf,"%sNNTP_GATE@%s",pth,Hostname);
  3653.  
  3654.     path = strdup(buf);
  3655.  
  3656.     rewind(data);
  3657.  
  3658.     while((fgets(buf,LINELEN,data)) != 0) {
  3659.  
  3660.         if(htype(buf) == DATE)
  3661.  
  3662.             break;
  3663.  
  3664.         if(htype(buf) == RECEIVED) {
  3665.  
  3666.             cp = strchr(buf,' ');
  3667.  
  3668.             cp++;
  3669.  
  3670.             cp = strchr(cp, ' ');
  3671.  
  3672.             cp++;
  3673.  
  3674.             cp1 = strpbrk(cp, ". \0");
  3675.  
  3676.             *cp1 = '\0';
  3677.  
  3678.             cp1 = mallocw(strlen(path)+strlen(cp)+2);  /* */
  3679.  
  3680.             sprintf(cp1,"%s!%s",path,cp);
  3681.  
  3682.             free(path);
  3683.  
  3684.             path = cp1;
  3685.  
  3686.         }
  3687.  
  3688.     }
  3689.  
  3690.     return(path);
  3691.  
  3692. }
  3693.  
  3694.  
  3695.  
  3696. int
  3697.  
  3698. nnGpost(FILE *data,char *from,struct list *le)
  3699.  
  3700. {
  3701.  
  3702.     struct nntpsv *mp;
  3703.  
  3704.     char buf[LINELEN], *cp;
  3705.  
  3706.     FILE *f, *idf;
  3707.  
  3708.     int32 id;
  3709.  
  3710.     int strl;
  3711.  
  3712.     long currtime;
  3713.  
  3714.  
  3715.  
  3716.     if (!Filecheck)
  3717.  
  3718.         if(check_system())
  3719.  
  3720.             return -1;
  3721.  
  3722.  
  3723.  
  3724.     if ((f = temp_file(0,1)) == NULLFILE)
  3725.  
  3726.         return -1;
  3727.  
  3728.  
  3729.  
  3730.     mp = (struct nntpsv *)callocw(1,sizeof(struct nntpsv));
  3731.  
  3732.  
  3733.  
  3734.     /* build postuser */
  3735.  
  3736.     cp = mkreplypath(data);
  3737.  
  3738.     fprintf(f,"%s\n",cp);
  3739.  
  3740.     free((char *)cp);
  3741.  
  3742.     fprintf(f,"%s%s\n",frm,from);
  3743.  
  3744.     /*----------------------------------------------------------------*
  3745.  
  3746.     * build newsgroup                                                 *
  3747.  
  3748.     *-----------------------------------------------------------------*/
  3749.  
  3750.     if((cp = strchr(le->val,'@')) != NULLCHAR)
  3751.  
  3752.         *cp = '\0';
  3753.  
  3754.     strcpy(buf,le->val); 
  3755.     cp=buf;
  3756.     strl = strlen(cp);
  3757.  
  3758.     while(*cp != '\0') {
  3759.  
  3760.         if(*cp == '!') *cp = '.'; /* change ! into . - yc1dav */
  3761.  
  3762.         cp++; 
  3763.  
  3764.      
  3765.     }
  3766.  
  3767.     fprintf(f,"%s%s\n",ngrps,(cp-strl+1));  /* skip the first "." */
  3768.     
  3769.     /*----------------------------------------------------------------*
  3770.  
  3771.     * find the subject
  3772.  
  3773.     *-----------------------------------------------------------------*/
  3774.  
  3775.     rewind (data);
  3776.  
  3777.     while((fgets(buf,sizeof(buf),data))!=0)   {
  3778.  
  3779.         if (htype(buf)== SUBJECT)
  3780.  
  3781.             break;
  3782.  
  3783.         continue;
  3784.  
  3785.     }
  3786.  
  3787.     fputs((*buf == 0) ? "Subject: (none)\n" : buf,f);
  3788.  
  3789.     /*-------------------------------------------------------------------*
  3790.  
  3791.     * use msgid of original message
  3792.  
  3793.     *--------------------------------------------------------------------*/
  3794.  
  3795.     rewind(data);
  3796.  
  3797.     while((fgets(buf,sizeof(buf),data))!=0)   {
  3798.  
  3799.         if (htype(buf)== MSGID)
  3800.  
  3801.             break;
  3802.  
  3803.         continue;
  3804.  
  3805.     }
  3806.  
  3807.     if (*buf == 0)   {
  3808.  
  3809.         sprintf(buf,"%s/sequence.seq",Mailqdir);
  3810.  
  3811.         idf = open_file(buf,"r+",0,1);
  3812.  
  3813.         id = atol(fgets(buf,LineLen,idf));
  3814.  
  3815.         rewind(idf);
  3816.  
  3817.         fprintf(idf,"%ld",id+2);
  3818.  
  3819.         fclose(idf);
  3820.  
  3821.         fprintf(f,"%s<%ld@%s>\n",msgid,id,Hostname);
  3822.  
  3823.         sprintf(mp->buf,"<%ld@%s>",id,Hostname);
  3824.  
  3825.     } else {
  3826.  
  3827.         fputs(buf,f);
  3828.  
  3829.         rip(buf);
  3830.  
  3831.         cp = strchr(buf,'<');
  3832.  
  3833.         strcpy(mp->buf,cp);
  3834.  
  3835.         if (check_article(mp->buf))
  3836.  
  3837.             goto quit;
  3838.  
  3839.     }
  3840.  
  3841.     rewind (data);
  3842.  
  3843.     time(&currtime);
  3844.  
  3845.     fprintf(f,"Sender: NNTP@%s\n",Hostname);
  3846.  
  3847.     /*-------------------------------------------------------------------*
  3848.  
  3849.     * message follows                                                    *
  3850.  
  3851.     *--------------------------------------------------------------------*/
  3852.  
  3853.     fputs("Comments: Message transferred from SMTP\n",f);
  3854.  
  3855.     while((fgets(buf,sizeof(buf),data))!=0)   {
  3856.  
  3857.         switch(htype(buf))   {
  3858.  
  3859.             case FROM:
  3860.  
  3861.             case MSGID:
  3862.  
  3863.             case RECEIVED:
  3864.  
  3865.                 fgets(buf,sizeof(buf),data); /*eat the id*/
  3866.  
  3867.                 continue;
  3868.  
  3869.         }
  3870.  
  3871.         fputs(buf,f);
  3872.  
  3873.     }
  3874.  
  3875.     rewind(f);
  3876.  
  3877.     mp->id = strdup(mp->buf);
  3878.  
  3879.     xfer_article2(f,mp);
  3880.  
  3881. /*
  3882.  
  3883.     log(-1,"NNGT: transfer: Msg %s",mp->id);
  3884.  
  3885. */
  3886.  
  3887. quit:
  3888.  
  3889.     fclose(f);
  3890.  
  3891.     free(mp);
  3892.  
  3893.     return 0;
  3894.  
  3895. }
  3896.  
  3897.  
  3898.  
  3899. /* ---------------------------- Servercmd --------------------------- */
  3900.  
  3901.  
  3902.  
  3903. /* Start up NNTP receiver service */
  3904.  
  3905. int
  3906.  
  3907. nntp1(argc,argv,p)
  3908.  
  3909. int argc;
  3910.  
  3911. char *argv[];
  3912.  
  3913. void *p;
  3914.  
  3915. {
  3916.  
  3917.     struct sockaddr_in lsocket;
  3918.  
  3919.     int s;
  3920.  
  3921.  
  3922.  
  3923.     if(Snntp != -1)
  3924.  
  3925.         return -1;
  3926.  
  3927.     if(check_system() == -1)
  3928.  
  3929.         return -1;
  3930.  
  3931.  
  3932.  
  3933.     psignal(Curproc,0);     /* Don't keep the parser waiting */
  3934.  
  3935.     chname(Curproc,"NNTP listener");
  3936.  
  3937.  
  3938.  
  3939.     lsocket.sin_family = AF_INET;
  3940.  
  3941.     lsocket.sin_addr.s_addr = INADDR_ANY;
  3942.  
  3943.     lsocket.sin_port = (argc < 2) ? IPPORT_NNTP : atoi(argv[1]);
  3944.  
  3945.  
  3946.  
  3947.     Snntp = socket(AF_INET,SOCK_STREAM,0);
  3948.  
  3949.     bind(Snntp,(char *)&lsocket,sizeof(lsocket));
  3950.  
  3951.     listen(Snntp,1);
  3952.  
  3953.  
  3954.  
  3955.     for(;;){
  3956.  
  3957.         if((s = accept(Snntp,NULLCHAR,(int *)NULL)) == -1)
  3958.  
  3959.             break;  /* Service is shutting down */
  3960.  
  3961.  
  3962.  
  3963. #ifndef UNIX
  3964.  
  3965.         if(availmem() < Memthresh){
  3966.  
  3967.             usputs(s,lowmem);
  3968.  
  3969.             shutdown(s,1);
  3970.  
  3971.         } else {
  3972.  
  3973. #endif
  3974.  
  3975.             sockmode(s,SOCK_ASCII);
  3976.  
  3977.             /* Spawn a server */
  3978.  
  3979.             newproc("NNTP server",2048,nntpserv,s,NULL,NULL,0);
  3980.  
  3981. #ifndef UNIX
  3982.  
  3983.         }
  3984.  
  3985. #endif
  3986.  
  3987.     }
  3988.  
  3989.     return 0;
  3990.  
  3991. }
  3992.  
  3993.  
  3994.  
  3995. /* Shutdown NNTP service (existing connections are allowed to finish) */
  3996.  
  3997. int
  3998.  
  3999. nntp0(argc,argv,p)
  4000.  
  4001. int argc;
  4002.  
  4003. char *argv[];
  4004.  
  4005. void *p;
  4006.  
  4007. {
  4008.  
  4009.     close_s(Snntp);
  4010.  
  4011.     Snntp = -1;
  4012.  
  4013.     return 0;
  4014.  
  4015. }
  4016.  
  4017.  
  4018.  
  4019. /* ---------------------------- Subcmds --------------------------- */
  4020.  
  4021.  
  4022.  
  4023. /* lists active newsgroups
  4024.  
  4025.  * returncode: -1 if error; 0 success */
  4026.  
  4027. static int
  4028.  
  4029. donnactive(argc,argv,p)
  4030.  
  4031. int argc;
  4032.  
  4033. char *argv[];
  4034.  
  4035. void *p;
  4036.  
  4037. {
  4038.  
  4039.     FILE *fp;
  4040.  
  4041.     char line[80], *cp;
  4042.  
  4043.  
  4044.  
  4045.     if((fp = open_file(Active,READ_TEXT,0,1)) == NULLFILE)
  4046.  
  4047.         return -1;
  4048.  
  4049.  
  4050.  
  4051.     tputs("Msg#  next  mod newsgroup\n");
  4052.  
  4053.  
  4054.  
  4055.     for(;;) {
  4056.  
  4057.         if (fgets(line,sizeof(line),fp) == NULL)
  4058.  
  4059.             break;
  4060.  
  4061.         if((cp = strchr(line,' ')) == NULLCHAR)
  4062.  
  4063.             break;
  4064.  
  4065.         *cp = '\0';
  4066.  
  4067.         rip(++cp);
  4068.  
  4069.         tprintf("%s   %s\n",cp,line);
  4070.  
  4071.     }
  4072.  
  4073.     fclose(fp);
  4074.  
  4075.     return 0;
  4076.  
  4077. }
  4078.  
  4079.  
  4080.  
  4081. /* add nntp servers to list */
  4082.  
  4083. static int
  4084.  
  4085. donnadds(argc,argv,p)
  4086.  
  4087. int argc;
  4088.  
  4089. char *argv[];
  4090.  
  4091. void *p;
  4092.  
  4093. {
  4094.  
  4095.     struct Servers *np;
  4096.  
  4097.  
  4098.  
  4099.     for(np = Nntpserver; np != NULLSERVER; np = np->next)
  4100.  
  4101.         if(stricmp(np->name,argv[1]) == 0)
  4102.  
  4103.             break;
  4104.  
  4105.     if (np == NULLSERVER) {
  4106.  
  4107.         np = (struct Servers *)callocw(1,sizeof(struct Servers));
  4108.  
  4109.         if((np->dest = resolve(argv[1])) == 0) {
  4110.  
  4111.             tprintf(Badhost,argv[1]);
  4112.  
  4113.             free((char *)np);
  4114.  
  4115.             return -1;
  4116.  
  4117.         }
  4118.  
  4119.         np->name = strdup(argv[1]);
  4120.  
  4121.         np->next = Nntpserver;
  4122.  
  4123.         Nntpserver = np;
  4124.  
  4125.         np->newsgroups = NULLCHAR;
  4126.  
  4127.         np->lowtime = np->hightime = -1;
  4128.  
  4129.         np->nntpt.func = poll;          /* what to call on timeout */
  4130.  
  4131.         np->nntpt.arg = (void *)np;
  4132.  
  4133.     }
  4134.  
  4135.     if (argc > 3) {
  4136.  
  4137.         int i;
  4138.  
  4139.         if (np->newsgroups == NULLCHAR) {
  4140.  
  4141.             np->newsgroups = callocw(1,LineLen);
  4142.  
  4143.             *np->newsgroups = '\0';
  4144.  
  4145.         }
  4146.  
  4147.         for (i = 3; i < argc; ++i) {
  4148.  
  4149.             if (isdigit(*argv[i])) {
  4150.  
  4151.                 int lh, ll, hh, hl;
  4152.  
  4153.                 sscanf(argv[i], "%d:%d-%d:%d", &lh, &ll, &hh, &hl);
  4154.  
  4155.                 np->lowtime = lh * 100 + ll;
  4156.  
  4157.                 np->hightime = hh * 100 + hl;
  4158.  
  4159.             } else if ((strlen(np->newsgroups)+strlen(argv[i])+2) >= LineLen)
  4160.  
  4161.                 tprintf("To many groups, '%s' ignored\n", argv[i]);
  4162.  
  4163.             else {  /* it's a group, and it fits... add it to list */
  4164.  
  4165.                 if (*np->newsgroups != '\0')
  4166.  
  4167.                     strcat(np->newsgroups, ",");
  4168.  
  4169.                 strcat(np->newsgroups, argv[i]);
  4170.  
  4171.             }
  4172.  
  4173.         }
  4174.  
  4175.         if (*np->newsgroups == '\0') {  /* No groups specified? */
  4176.  
  4177.             free(np->newsgroups);
  4178.  
  4179.             np->newsgroups = NULLCHAR;
  4180.  
  4181.         }
  4182.  
  4183.     }
  4184.  
  4185.     /* set timer duration */
  4186.  
  4187.     set_timer(&np->nntpt,atol(argv[2])*1000L);
  4188.  
  4189.     start_timer(&np->nntpt);                /* and fire it up */
  4190.  
  4191.     return 0;
  4192.  
  4193. }
  4194.  
  4195.  
  4196.  
  4197. /* drops nntp servers from list */
  4198.  
  4199. static int
  4200.  
  4201. donndrops(argc,argv,p)
  4202.  
  4203. int argc;
  4204.  
  4205. char *argv[];
  4206.  
  4207. void *p;
  4208.  
  4209. {
  4210.  
  4211.     struct Servers *np, *npprev = NULLSERVER;
  4212.  
  4213.  
  4214.  
  4215.     for(np = Nntpserver; np != NULLSERVER; npprev = np, np = np->next)
  4216.  
  4217.         if(stricmp(np->name,argv[1]) == 0) {
  4218.  
  4219.             stop_timer(&np->nntpt);
  4220.  
  4221.             free(np->name);
  4222.  
  4223.             if (np->newsgroups)
  4224.  
  4225.                 free(np->newsgroups);
  4226.  
  4227.             if(npprev != NULLSERVER)
  4228.  
  4229.                 npprev->next = np->next;
  4230.  
  4231.             else
  4232.  
  4233.                 Nntpserver = np->next;
  4234.  
  4235.             free((char *)np);
  4236.  
  4237.             return 0;
  4238.  
  4239.     }
  4240.  
  4241.     tputs("No such server enabled.\n");
  4242.  
  4243.     return -1;
  4244.  
  4245. }
  4246.  
  4247.  
  4248.  
  4249. /* copies a news from given newsgroup to the mailbox */
  4250.  
  4251. static int
  4252.  
  4253. donndump(argc,argv,p)
  4254.  
  4255. int argc;
  4256.  
  4257. char *argv[];
  4258.  
  4259. void *p;
  4260.  
  4261. {
  4262.  
  4263.     FILE *t, *f, *o;
  4264.  
  4265.     char path[LineLen], line[LineLen], *cp, newsname[25], *cp1;
  4266.  
  4267.     struct ffblk blk;
  4268.  
  4269.  
  4270.  
  4271.     if (!Filecheck)
  4272.  
  4273.         if(check_system())
  4274.  
  4275.             return -1;
  4276.  
  4277.  
  4278.  
  4279.     if ((f = open_file(Pointer,READ_TEXT,0,1)) == NULLFILE)
  4280.  
  4281.         return 0;
  4282.  
  4283.  
  4284.  
  4285.     path[0] = '\0';
  4286.  
  4287.     line[0] = '\0';
  4288.  
  4289.  
  4290.  
  4291.     for(;;) {
  4292.  
  4293.         if (fgets(line,LineLen,f) == NULL)
  4294.  
  4295.             break;
  4296.  
  4297.         if (!strncmp(line,argv[1],strlen(argv[1]))) {
  4298.  
  4299.             cp = strchr(line,' ') + 1;
  4300.  
  4301.             strcpy(path,cp);
  4302.  
  4303.             break;
  4304.  
  4305.         }
  4306.  
  4307.     }
  4308.  
  4309.     fclose(f);
  4310.  
  4311.  
  4312.  
  4313.     if (path[0] == '\0') {
  4314.  
  4315.         tprintf("No newsgroup %s\n",argv[1]);
  4316.  
  4317.         goto error;
  4318.  
  4319.     }
  4320.  
  4321.  
  4322.  
  4323.     rip2(path);
  4324.  
  4325.     cp = strrchr(path,'/');
  4326.  
  4327.     cp1 = &newsname[0];
  4328.  
  4329.  
  4330.  
  4331.     while(*cp)
  4332.  
  4333.         *(cp1++) = *(cp++);
  4334.  
  4335.     *cp1 = '\0';
  4336.  
  4337.  
  4338.  
  4339.     strcpy(line,path);
  4340.  
  4341.     strcat(line,"/*.*");
  4342.  
  4343.     if(findfirst(line,&blk,0)) {
  4344.  
  4345.         tputs("No news in newsgroup\n");
  4346.  
  4347.         goto error;
  4348.  
  4349.     }
  4350.  
  4351.     if(argc > 2)
  4352.  
  4353.         sprintf(newsname,"/%s",argv[2]);
  4354.  
  4355.  
  4356.  
  4357.     sprintf(line,"%s%s.txt",Mailspool,newsname);
  4358.  
  4359.     if ((o = open_file(line,"a+",0,1)) == NULLFILE)
  4360.  
  4361.         goto error;
  4362.  
  4363.     if(!(mlock(Mailspool,newsname))) {
  4364.  
  4365.         tprintf("Newsgroup dump to %s\n",line);
  4366.  
  4367.         for (;;) {
  4368.  
  4369.             if((t = temp_file(0,1)) == NULLFILE) {
  4370.  
  4371.                 fclose(o);
  4372.  
  4373.                 goto error;
  4374.  
  4375.             }
  4376.  
  4377.             sprintf(line,"%s/%s",path,blk.ff_name);
  4378.  
  4379.             /* Open the article */
  4380.  
  4381.             if ((f = open_file(line,READ_TEXT,0,1)) == NULLFILE) {
  4382.  
  4383.                 fclose(t);
  4384.  
  4385.                 fclose(o);
  4386.  
  4387.                 goto error;
  4388.  
  4389.             }
  4390.  
  4391.             pwait(NULL);
  4392.  
  4393.             tputc('.'); /* One dot/article processed */
  4394.  
  4395.             tflush();
  4396.  
  4397.  
  4398.  
  4399.             for (;;) {
  4400.  
  4401.                 if (fgets(line,LineLen,f) == NULL)
  4402.  
  4403.                     break;
  4404.  
  4405.                 fputs(line,t);
  4406.  
  4407.                 if (!strnicmp(line,frm,6)) {
  4408.  
  4409.                     cp = strchr(line,' ')+1;
  4410.  
  4411.                     fprintf(o,"From %s",cp);
  4412.  
  4413.                 }
  4414.  
  4415.             }
  4416.  
  4417.             rewind(t);
  4418.  
  4419.             for(;;) {
  4420.  
  4421.                 if (fgets(line,LineLen,t) == NULL)
  4422.  
  4423.                     break;
  4424.  
  4425.                 fputs(line,o);
  4426.  
  4427.             }
  4428.  
  4429.             fputc('\n',o);
  4430.  
  4431.             fclose(t);
  4432.  
  4433.             fclose(f);
  4434.  
  4435.             if (findnext(&blk))
  4436.  
  4437.                 break;
  4438.  
  4439.         }
  4440.  
  4441.         rmlock(Mailspool,newsname);
  4442.  
  4443.     } else
  4444.  
  4445.         tputs("Mailfile is busy, try later");
  4446.  
  4447.     fclose(o);
  4448.  
  4449.     tputs("\n");
  4450.  
  4451.  
  4452.  
  4453. error:
  4454.  
  4455.     return 0;
  4456.  
  4457. }
  4458.  
  4459.  
  4460.  
  4461. static int
  4462.  
  4463. donnkick(argc,argv,p)
  4464.  
  4465. int argc;
  4466.  
  4467. char *argv[];
  4468.  
  4469. void *p;
  4470.  
  4471. {
  4472.  
  4473.     struct Servers *np;
  4474.  
  4475.  
  4476.  
  4477.     for(np = Nntpserver; np != NULLSERVER; np = np->next)
  4478.  
  4479.         if(!stricmp(np->name,argv[1])) {
  4480.  
  4481.             /* If the timer is not running, the timeout function has
  4482.  
  4483.              * already been called and we don't want to call it again.
  4484.  
  4485.              */
  4486.  
  4487.             if(run_timer(&np->nntpt) || dur_timer(&np->nntpt) == 0) {
  4488.  
  4489.                 stop_timer(&np->nntpt);
  4490.  
  4491.                 poll((void *)np);
  4492.  
  4493.             }
  4494.  
  4495.         return 0;
  4496.  
  4497.     }
  4498.  
  4499.     tputs("No server enabled\n");
  4500.  
  4501.     return 0;
  4502.  
  4503. }
  4504.  
  4505.  
  4506.  
  4507. #ifdef LZW
  4508.  
  4509. /* sets LzwActive flag */
  4510.  
  4511. static int
  4512.  
  4513. donnlzw(argc,argv,p)
  4514.  
  4515. int argc;
  4516.  
  4517. char *argv[];
  4518.  
  4519. void *p;
  4520.  
  4521. {
  4522.  
  4523.     return setbool(&LzwActive,"NNTP LZW",argc,argv);
  4524.  
  4525. }
  4526.  
  4527. #endif
  4528.  
  4529.  
  4530.  
  4531. /* list nntp servers */
  4532.  
  4533. static int
  4534.  
  4535. donnlists(argc,argv,p)
  4536.  
  4537. int argc;
  4538.  
  4539. char *argv[];
  4540.  
  4541. void *p;
  4542.  
  4543. {
  4544.  
  4545.     struct Servers *np;
  4546.  
  4547.     char tbuf[80];
  4548.  
  4549.  
  4550.  
  4551.     for(np = Nntpserver; np != NULLSERVER; np = np->next) {
  4552.  
  4553.         if (np->lowtime != -1 && np->hightime != -1)
  4554.  
  4555.             sprintf(tbuf, " -- %02d:%02d-%02d:%02d",
  4556.  
  4557.                 np->lowtime/100, np->lowtime%100,
  4558.  
  4559.                 np->hightime/100, np->hightime%100);
  4560.  
  4561.         else
  4562.  
  4563.             tbuf[0] = '\0';
  4564.  
  4565.         tprintf("%-32s (%lu/%lu%s)\n   Groups: %s\n", np->name,
  4566.  
  4567.             read_timer(&np->nntpt) /1000L,
  4568.  
  4569.             dur_timer(&np->nntpt) /1000L,
  4570.  
  4571.             tbuf, np->newsgroups ? np->newsgroups : "");
  4572.  
  4573.     }
  4574.  
  4575.     return 0;
  4576.  
  4577. }
  4578.  
  4579.  
  4580.  
  4581. /* manually entering new news
  4582.  
  4583.  * returncode: -1 if error; 0 success */
  4584.  
  4585. static int
  4586.  
  4587. donnpost(argc,argv,p)
  4588.  
  4589. int argc;
  4590.  
  4591. char *argv[];
  4592.  
  4593. void *p;
  4594.  
  4595. {
  4596.  
  4597.     struct session *sp;
  4598.  
  4599.     struct nntpsv *mp;
  4600.  
  4601.     char buf[LineLen];
  4602.  
  4603.     int id;
  4604.  
  4605.     FILE *f, *idf, *ufp;
  4606.  
  4607.     long currtime;
  4608.  
  4609.  
  4610.  
  4611.     if (!Filecheck)
  4612.  
  4613.         if(check_system())
  4614.  
  4615.             return -1;
  4616.  
  4617.  
  4618.  
  4619.     if((sp = newsession("Post",0,1)) == NULLSESSION)
  4620.  
  4621.         return -1;
  4622.  
  4623.  
  4624.  
  4625.     mp = (struct nntpsv *)callocw(1,sizeof(struct nntpsv));
  4626.  
  4627.  
  4628.  
  4629.     for (;;) {
  4630.  
  4631.         if ((f = temp_file(0,1)) == NULLFILE)
  4632.  
  4633.             goto done;
  4634.  
  4635.  
  4636.  
  4637.         sprintf(buf,"%s/sequence.seq",Mailqdir);
  4638.  
  4639.         if ((idf = open_file(buf,"r+",0,1)) == NULLFILE) {
  4640.  
  4641.             tprintf("Please create %s dir ...\n",Mailqdir);
  4642.  
  4643.             fclose(f);
  4644.  
  4645.             goto done;
  4646.  
  4647.         }
  4648.  
  4649.  
  4650.  
  4651.         id = atoi(fgets(buf,LineLen,idf));
  4652.  
  4653.         rewind(idf);
  4654.  
  4655.         fprintf(idf,"%d",id+2);
  4656.  
  4657.         fclose(idf);
  4658.  
  4659.  
  4660.  
  4661.         if (Post->user == NULLCHAR) {
  4662.  
  4663.             tputs("User name? ");
  4664.  
  4665.             recvline(sp->input,buf,LineLen);
  4666.  
  4667.             rip2(buf);
  4668.  
  4669.             Post->user = strdup(buf);
  4670.  
  4671.         }
  4672.  
  4673.         fprintf(f,"%s%s\n",pth,Post->user);
  4674.  
  4675.         fprintf(f,"%s%s@%s",frm,Post->user,Hostname);
  4676.  
  4677.         if (Post->fullname != NULLCHAR)
  4678.  
  4679.             fprintf(f," (%s )",Post->fullname);
  4680.  
  4681.         fputc('\n',f);
  4682.  
  4683.  
  4684.  
  4685.         tputs("Newsgroup? ");
  4686.  
  4687.         recvline(sp->input,buf,LineLen);
  4688.  
  4689.         rip2(buf);
  4690.  
  4691.         if (check_blank(buf))
  4692.  
  4693.             goto done;
  4694.  
  4695.         fprintf(f,"%s%s\n",ngrps,buf);
  4696.  
  4697.  
  4698.  
  4699.         tputs("Subject? ");
  4700.  
  4701.         recvline(sp->input,buf,LineLen);
  4702.  
  4703.         fprintf(f,"%s%s",subj,buf);
  4704.  
  4705.         fprintf(f,"%s<%d@%s>\n",msgid,id,Hostname);
  4706.  
  4707.         time(&currtime);
  4708.  
  4709.         fprintf(f,"Date: %s",ptime(&currtime));
  4710.  
  4711.         fprintf(f,"Sender: NNTP@%s\n",Hostname);
  4712.  
  4713.  
  4714.  
  4715.         if (Post->reply != NULLCHAR)
  4716.  
  4717.             fprintf(f,"%s%s\n",replyto,Post->reply);
  4718.  
  4719.  
  4720.  
  4721.         if (Post->organ != NULLCHAR)
  4722.  
  4723.             fprintf(f,"Organization: %s\n",Post->organ);
  4724.  
  4725.  
  4726.  
  4727.         fputc('\n',f);
  4728.  
  4729.         tputs("Enter message - end with .\n");
  4730.  
  4731.  
  4732.  
  4733.         for (;;) {
  4734.  
  4735.             recvline(sp->input,buf,LineLen);
  4736.  
  4737.             if(strcmp(buf,".u\n") == 0
  4738.  
  4739.               || strcmp(buf,".r\n") == 0) {
  4740.  
  4741.                 tputs("Filename? ");
  4742.  
  4743.                 recvline(sp->input,buf,LineLen);
  4744.  
  4745.                 rip2(buf);
  4746.  
  4747.                 if((ufp = open_file(buf,READ_TEXT,0,1)) != NULLFILE) {
  4748.  
  4749.                     while(fgets(buf,LineLen,ufp) != NULL)
  4750.  
  4751.                         fputs(buf,f);
  4752.  
  4753.                     fclose(ufp);
  4754.  
  4755.                 }
  4756.  
  4757.                 tputs("(continue)\n");
  4758.  
  4759.             }
  4760.  
  4761.             if(strcmp(buf,".\n") == 0
  4762.  
  4763.               || strcmpi(buf,"***END\n") == 0
  4764.  
  4765.               || strcmpi(buf,"/EX\n") == 0)
  4766.  
  4767.                 break;
  4768.  
  4769.             fputs(buf,f);
  4770.  
  4771.         }
  4772.  
  4773.  
  4774.  
  4775.         if (Post->sig != NULLCHAR) {
  4776.  
  4777.             sprintf(buf,"%s",Post->sig);
  4778.  
  4779.             if ((idf = open_file(buf,READ_TEXT,0,1)) != NULLFILE ) {
  4780.  
  4781.                 while(fgets(buf,LineLen,idf) != NULL)
  4782.  
  4783.                     fputs(buf,f);
  4784.  
  4785.                 fclose(idf);
  4786.  
  4787.             }
  4788.  
  4789.         }
  4790.  
  4791.  
  4792.  
  4793. loop:   tputs("\n[Send, Abort, Exit, List] ");
  4794.  
  4795.         recvline(sp->input,buf,LineLen);
  4796.  
  4797.         switch(tolower(buf[0])) {
  4798.  
  4799.         case 's':
  4800.  
  4801.             rewind(f);
  4802.  
  4803.             sprintf(mp->buf,"<%d@%s>",id,Hostname);
  4804.  
  4805.             mp->id = strdup(mp->buf);
  4806.  
  4807.             xfer_article2(f,mp);
  4808.  
  4809.             break;
  4810.  
  4811.         case 'l':
  4812.  
  4813.             rewind(f);
  4814.  
  4815.             for(;;) {
  4816.  
  4817.                 if (fgets(buf,LineLen,f) == NULL)
  4818.  
  4819.                     break;
  4820.  
  4821.                 tputs(buf);
  4822.  
  4823.             }
  4824.  
  4825.             rewind(f);
  4826.  
  4827.             goto loop;
  4828.  
  4829.         case 'e':
  4830.  
  4831.             fclose(f);
  4832.  
  4833.             goto done;
  4834.  
  4835.         case 'a':
  4836.  
  4837.             break;
  4838.  
  4839.         default:
  4840.  
  4841.             goto loop;
  4842.  
  4843.         }
  4844.  
  4845.         fclose(f);
  4846.  
  4847.         tputs("Post another? ");
  4848.  
  4849.         recvline(sp->input,buf,LineLen);
  4850.  
  4851.         if (tolower(buf[0]) == 'n')
  4852.  
  4853.             goto done;
  4854.  
  4855.     }
  4856.  
  4857.  
  4858.  
  4859. done:
  4860.  
  4861.     if(f != NULLFILE)
  4862.  
  4863.         fclose(f);
  4864.  
  4865.     keywait(NULLCHAR,1);
  4866.  
  4867.     free((char *) mp);
  4868.  
  4869.     freesession(sp);
  4870.  
  4871.     return 0;
  4872.  
  4873. }
  4874.  
  4875.  
  4876.  
  4877. static int
  4878.  
  4879. donnquiet(argc,argv,p)
  4880.  
  4881. int argc;
  4882.  
  4883. char *argv[];
  4884.  
  4885. void *p;
  4886.  
  4887. {
  4888.  
  4889.     return setintrc(&Nntpquiet,"NNTP quiet",argc,argv,0,2);
  4890.  
  4891. }
  4892.  
  4893.  
  4894.  
  4895. /* -------------------- Profile subcmds -------------------- */
  4896.  
  4897.  
  4898.  
  4899. static int
  4900.  
  4901. donnuser(argc,argv,p)
  4902.  
  4903. int argc;
  4904.  
  4905. char *argv[];
  4906.  
  4907. void *p;
  4908.  
  4909. {
  4910.  
  4911.     if(argc < 2 && Post->user != NULLCHAR)
  4912.  
  4913.         tprintf("%s\n",Post->user);
  4914.  
  4915.     else {
  4916.  
  4917.         free(Post->user);
  4918.  
  4919.         Post->user = strdup(argv[1]);
  4920.  
  4921.     }
  4922.  
  4923.     return 0;
  4924.  
  4925. }
  4926.  
  4927.  
  4928.  
  4929. static int
  4930.  
  4931. donnsig(argc,argv,p)
  4932.  
  4933. int argc;
  4934.  
  4935. char *argv[];
  4936.  
  4937. void *p;
  4938.  
  4939. {
  4940.  
  4941.     if(argc < 2 && Post->sig != NULLCHAR)
  4942.  
  4943.         tprintf("%s\n",Post->sig);
  4944.  
  4945.     else {
  4946.  
  4947.         if(access(argv[1],0) == 0) {
  4948.  
  4949.             free(Post->sig);
  4950.  
  4951.             Post->sig = strdup(argv[1]);
  4952.  
  4953.         } else {
  4954.  
  4955.             tputs("No such signature file\n");
  4956.  
  4957.             return -1;
  4958.  
  4959.         }
  4960.  
  4961.     }
  4962.  
  4963.     return 0;
  4964.  
  4965. }
  4966.  
  4967.  
  4968.  
  4969. static int
  4970.  
  4971. donnfull(argc,argv,p)
  4972.  
  4973. int argc;
  4974.  
  4975. char *argv[];
  4976.  
  4977. void *p;
  4978.  
  4979. {
  4980.  
  4981.     if(argc < 2 && Post->fullname != NULLCHAR)
  4982.  
  4983.         tprintf("%s\n",Post->fullname);
  4984.  
  4985.     else {
  4986.  
  4987.         free(Post->fullname);
  4988.  
  4989.         Post->fullname = strdup(argv[1]);
  4990.  
  4991.     }
  4992.  
  4993.     return 0;
  4994.  
  4995. }
  4996.  
  4997.  
  4998.  
  4999. static int
  5000.  
  5001. donnhost(argc,argv,p)
  5002.  
  5003. int argc;
  5004.  
  5005. char *argv[];
  5006.  
  5007. void *p;
  5008.  
  5009. {
  5010.  
  5011.     if(argc < 2 && Host != NULLCHAR)
  5012.  
  5013.         tprintf("%s\n",Host);
  5014.  
  5015.     else {
  5016.  
  5017.         free(Host);
  5018.  
  5019.         Host = strdup(argv[1]);
  5020.  
  5021.     }
  5022.  
  5023.     return 0;
  5024.  
  5025. }
  5026.  
  5027.  
  5028.  
  5029. static int
  5030.  
  5031. donnihave(argc,argv,p)
  5032.  
  5033. int argc;
  5034.  
  5035. char *argv[];
  5036.  
  5037. void *p;
  5038.  
  5039. {
  5040.  
  5041.     return setintrc(&NnIhave,"NNTP Ihave",argc,argv,0,2);
  5042.  
  5043. }
  5044.  
  5045.  
  5046.  
  5047. static int
  5048.  
  5049. donnorgan(argc,argv,p)
  5050.  
  5051. int argc;
  5052.  
  5053. char *argv[];
  5054.  
  5055. void *p;
  5056.  
  5057. {
  5058.  
  5059.     if(argc < 2 && Post->organ != NULLCHAR)
  5060.  
  5061.         tprintf("%s\n",Post->organ);
  5062.  
  5063.     else {
  5064.  
  5065.         free(Post->organ);
  5066.  
  5067.         Post->organ = strdup(argv[1]);
  5068.  
  5069.     }
  5070.  
  5071.     return 0;
  5072.  
  5073. }
  5074.  
  5075.  
  5076.  
  5077. static int
  5078.  
  5079. donnread(argc,argv,p)
  5080.  
  5081. int argc;
  5082.  
  5083. char *argv[];
  5084.  
  5085. void *p;
  5086.  
  5087. {
  5088.  
  5089.     FILE *f;
  5090.  
  5091.     struct session *sp;
  5092.  
  5093.     struct article *art;
  5094.  
  5095.     char cp[LINELEN], buf[81];
  5096.  
  5097.     int number, row, Nrows=NROWS, flag = argc;
  5098.  
  5099.  
  5100.  
  5101.     if((art = (struct article *)mallocw(sizeof(struct article))) == NULLARTICLE)
  5102.  
  5103.         return -1;
  5104.  
  5105.  
  5106.  
  5107.     art->group = strdup(argv[1]);
  5108.  
  5109.     if(get_path2(art) == 1) {
  5110.  
  5111.         if(argc > 2) {
  5112.  
  5113.             number = atoi(argv[2]);
  5114.  
  5115.         } else
  5116.  
  5117.             number = 1;
  5118.  
  5119.  
  5120.  
  5121.         sprintf(cp,"%s/news.rc",art->path);
  5122.  
  5123.         if(flag < 3 && (f = fopen(cp,READ_TEXT)) != NULLFILE) {
  5124.  
  5125.             if((fgets(buf,sizeof(buf),f)) != 0) {
  5126.  
  5127.                 number = atoi(buf);
  5128.  
  5129.                 number++;
  5130.  
  5131.             }
  5132.  
  5133.             fclose(f);
  5134.  
  5135.         }
  5136.  
  5137.         if((sp = newsession("NNTP read",MORE,0)) != NULLSESSION) {
  5138.  
  5139.             for(;;) {
  5140.  
  5141.                 if(number < 1)
  5142.  
  5143.                     number = 1;
  5144.  
  5145.                 sp->ttystate.echo = sp->ttystate.edit = 0;
  5146.  
  5147.                 row = Nrows - 4;
  5148.  
  5149.                 sprintf(cp,"%s/%d",art->path,number);
  5150.  
  5151.  
  5152.  
  5153.                 if((f = fopen(cp,READ_TEXT)) != NULLFILE) {
  5154.  
  5155.                     tprintf("Msg #%d\n",number);
  5156.  
  5157.                     while(fgets(buf,sizeof(buf),f),!feof(f)) {
  5158.  
  5159.                         tputs(buf);
  5160.  
  5161.                         if(--row == 0){
  5162.  
  5163.                             row = keywait("--More--",0);
  5164.  
  5165.                             switch(row){
  5166.  
  5167.                             case -1:
  5168.  
  5169.                             case 'q':
  5170.  
  5171.                                 fclose(f);
  5172.  
  5173.                                 goto done;
  5174.  
  5175.                             case '\n':
  5176.  
  5177.                             case '\r':
  5178.  
  5179.                                 row = 2;
  5180.  
  5181.                                 break;
  5182.  
  5183.                             default:
  5184.  
  5185.                                 row = Nrows - 3;
  5186.  
  5187.                             }
  5188.  
  5189.                         }
  5190.  
  5191.                     }
  5192.  
  5193.                     fclose(f);
  5194.  
  5195.                 } else {
  5196.  
  5197.                     number--;
  5198.  
  5199.                     tputs("No more news");
  5200.  
  5201.                 }
  5202.  
  5203. done:
  5204.  
  5205.                 row = keywait("\nRead next/previous? (n/p/q)",0);
  5206.  
  5207.                 switch(row) {
  5208.  
  5209.                     case -1:
  5210.  
  5211.                     case 'q':
  5212.  
  5213.                         goto done2;
  5214.  
  5215.                     case 'p':
  5216.  
  5217.                         flag = 3;
  5218.  
  5219.                         if(--number < 1)
  5220.  
  5221.                             goto done2;
  5222.  
  5223.                         continue;
  5224.  
  5225.                     default:
  5226.  
  5227.                         number++;
  5228.  
  5229.                         continue;
  5230.  
  5231.                 }
  5232.  
  5233.             }
  5234.  
  5235. done2:
  5236.  
  5237.             if(flag < 3) {
  5238.  
  5239.                 sprintf(cp,"%s/news.rc",art->path);
  5240.  
  5241.                 if((f = fopen(cp,WRITE_TEXT)) != NULLFILE) {
  5242.  
  5243.                     sprintf(cp,"%d\n",number);
  5244.  
  5245.                     fputs(cp,f);
  5246.  
  5247.                     fclose(f);
  5248.  
  5249.                 }
  5250.  
  5251.             }
  5252.  
  5253.             keywait(NULLCHAR,1);
  5254.  
  5255.             freesession(sp);
  5256.  
  5257.         }
  5258.  
  5259.     } else {
  5260.  
  5261.         tprintf("No such newsgroup %s\n",art->group);
  5262.  
  5263.     }
  5264.  
  5265.     free(art->path);
  5266.  
  5267.     free(art->group);
  5268.  
  5269.     free(art);
  5270.  
  5271.     return 0;
  5272.  
  5273. }
  5274.  
  5275.  
  5276.  
  5277. static int
  5278.  
  5279. donnreply(argc,argv,p)
  5280.  
  5281. int argc;
  5282.  
  5283. char *argv[];
  5284.  
  5285. void *p;
  5286.  
  5287. {
  5288.  
  5289.     if(argc < 2 && Post->reply != NULLCHAR)
  5290.  
  5291.         tprintf("%s\n",Post->reply);
  5292.  
  5293.     else {
  5294.  
  5295.         free(Post->reply);
  5296.  
  5297.         Post->reply = strdup(argv[1]);
  5298.  
  5299.     }
  5300.  
  5301.     return 0;
  5302.  
  5303. }
  5304.  
  5305.  
  5306.  
  5307. /* subcmd parser */
  5308.  
  5309. static int
  5310.  
  5311. donnprofile(argc,argv,p)
  5312.  
  5313. int argc;
  5314.  
  5315. char *argv[];
  5316.  
  5317. void *p;
  5318.  
  5319. {
  5320.  
  5321.      struct cmds Prof[] = {
  5322.  
  5323.         "fullname",     donnfull,       0, 0, NULLCHAR,
  5324.  
  5325.         "host",         donnhost,       0, 0, NULLCHAR,
  5326.  
  5327.         "organ",        donnorgan,      0, 0, NULLCHAR,
  5328.  
  5329.         "reply",        donnreply,      0, 0, NULLCHAR,
  5330.  
  5331.         "sig",          donnsig,        0, 0, NULLCHAR,
  5332.  
  5333.         "user",         donnuser,       0, 0, NULLCHAR,
  5334.  
  5335.         NULLCHAR,
  5336.  
  5337.     };
  5338.  
  5339.     if(Post == NULLPOST) {
  5340.  
  5341.         Post = (struct post *)callocw(1,sizeof(struct post));
  5342.  
  5343.         Post->user = Post->reply = Post->sig = Post->organ = Post->fullname = NULLCHAR;
  5344.  
  5345.     }
  5346.  
  5347.     if (Host == NULLCHAR) {
  5348.  
  5349.         Host = strdup(Hostname);
  5350.  
  5351.     }
  5352.  
  5353.     return (argc == 10) ? 0 : (subcmd(Prof,argc,argv,p));
  5354.  
  5355. }
  5356.  
  5357.  
  5358.  
  5359. /* cmd parser */
  5360.  
  5361. int
  5362.  
  5363. donntp(argc,argv,p)
  5364.  
  5365. int argc;
  5366.  
  5367. char *argv[];
  5368.  
  5369. void *p;
  5370.  
  5371. {
  5372.  
  5373.      struct cmds Nntp[] = {
  5374.  
  5375.         "active",       donnactive,     0,      0, NULLCHAR,
  5376.  
  5377.         "add",          donnadds,       0,      3, "nntp add <nntpserv> <interval> [<groups>]",
  5378.  
  5379.         "drop",         donndrops,      0,      2, "nntp drop <nntpserv>",
  5380.  
  5381.         "dump",         donndump,       0,      2, "nntp dump <newsgroup> [<mailbox>]",
  5382.  
  5383.         "ihave",        donnihave,      0,      0, NULLCHAR,
  5384.  
  5385.         "kick",         donnkick,       0,      2, "nntp kick <server>",
  5386.  
  5387.         "list",         donnlists,      0,      0, NULLCHAR,
  5388.  
  5389. #ifdef LZW
  5390.  
  5391.         "lzw",          donnlzw,        0,      0, NULLCHAR,
  5392.  
  5393. #endif
  5394.  
  5395.         "post",         donnpost,       2024,   0, NULLCHAR,
  5396.  
  5397.         "profile",      donnprofile,    0,      0, NULLCHAR,
  5398.  
  5399.         "read",         donnread,       1024,   2, "nntp read <newsgroup> [number]",
  5400.  
  5401.         "quiet",        donnquiet,      0,      0, NULLCHAR,
  5402.  
  5403.         NULLCHAR,
  5404.  
  5405.     };
  5406.  
  5407.  
  5408.  
  5409.     return (subcmd(Nntp,argc,argv,p));
  5410.  
  5411. }
  5412.  
  5413.  
  5414.  
  5415. /* main file-opening routine
  5416.  
  5417.  * options: s = socketnumber, if given an error msg is printed to the socket
  5418.  
  5419.  * returncode: NULLFILE if error; filepointer success
  5420.  
  5421.  */
  5422.  
  5423. FILE *
  5424.  
  5425. open_file(name,mode,s,t)
  5426.  
  5427. char *name;
  5428.  
  5429. char *mode;
  5430.  
  5431. int s;
  5432.  
  5433. int t;
  5434.  
  5435. {
  5436.  
  5437.     FILE *f;
  5438.  
  5439. #ifdef MSDOS
  5440.     register char *cp;
  5441. #endif
  5442.  
  5443.  
  5444.  
  5445.     if(name == NULLCHAR || mode == NULLCHAR)
  5446.  
  5447.         return NULLFILE;
  5448.  
  5449. #ifdef MSDOS
  5450.  
  5451.     while((cp = strchr(name,'\\')) != NULLCHAR)
  5452.  
  5453.         *cp = '/';
  5454.  
  5455. #endif
  5456.  
  5457.     if((f = fopen(name,mode)) == NULLFILE) {
  5458.  
  5459.         if(s)
  5460.  
  5461.             usprintf(s,fatal,name);
  5462.  
  5463.         if(t)
  5464.  
  5465.             tprintf("Can't open %s: %s\n",name,sys_errlist[errno]);
  5466.  
  5467.     }
  5468.  
  5469.     return f;
  5470.  
  5471. }
  5472.  
  5473.  
  5474.  
  5475. /* main tempfile-opening routine
  5476.  
  5477.  * returncode: NULLFILE if error; filepointer success
  5478.  
  5479.  */
  5480.  
  5481. FILE *
  5482.  
  5483. temp_file(s,t)
  5484.  
  5485. int s;
  5486.  
  5487. int t;
  5488.  
  5489. {
  5490.  
  5491.     FILE *f;
  5492.  
  5493.  
  5494.  
  5495.     if((f = tmpfile()) == NULLFILE) {
  5496.  
  5497.         if(s)
  5498.  
  5499.             usprintf(s,fatal,"TMP");
  5500.  
  5501.         if(t) {
  5502.  
  5503.             tprintf("Can't open TMP: %s\n",sys_errlist[errno]);
  5504.  
  5505.         }
  5506.  
  5507.     }
  5508.  
  5509.     return f;
  5510.  
  5511. }
  5512.  
  5513.  
  5514.  
  5515. #endif /* NNTPS */
  5516.  
  5517.  
  5518.  
  5519.